qint64 AssemblyModel::getModelHeight(U2OpStatus & os) { if(NO_VAL == cachedModelHeight) { U2AttributeDbi * attributeDbi = dbiHandle.dbi->getAttributeDbi(); if(attributeDbi != NULL) { U2IntegerAttribute attr = U2AttributeUtils::findIntegerAttribute(attributeDbi, assembly.id, U2BaseAttributeName::max_prow, os); LOG_OP(os); if(attr.hasValidId()) { if(attr.version == assembly.version) { cachedModelHeight = attr.value; } else if(checkPermissions(QFile::WriteUser,false)) { U2AttributeUtils::removeAttribute(attributeDbi, attr.id, os); LOG_OP(os); } } } if(cachedModelHeight == NO_VAL) { // if could not get value from attribute, recompute the value... cachedModelHeight = assemblyDbi->getMaxPackedRow(assembly.id, U2Region(0, getModelLength(os)), os); LOG_OP(os); if(! os.isCoR()) { // ...and store it in a new attribure U2IntegerAttribute attr; U2AttributeUtils::init(attr, assembly, U2BaseAttributeName::max_prow); attr.value = cachedModelHeight; attributeDbi->createIntegerAttribute(attr, os); } } if(cachedModelHeight == NO_VAL){ os.setError("Can't get model height, database is corrupted"); LOG_OP(os); } } return cachedModelHeight; }
//off_t lseek(int fd, off_t offset, int whence); off_t posix_lseek(const char *path, int fd, off_t offset, int whence) { off_t ret; char whenceBuf[16]; const char *whenceStr; switch (whence ) { case SEEK_SET: whenceStr = "SEEK_SET"; break; case SEEK_CUR: whenceStr = "SEEK_CUR"; break; case SEEK_END: whenceStr = "SEEK_END"; break; default: snprintf(whenceBuf, sizeof(whenceBuf), "%d", whence); whenceStr = whenceBuf; } ret = lseek(fd, offset, whence); LOG_OP(ret == (off_t) -1, errno, "lseek(fd=%d offset=%llu whence=%s) path='%s' ret=%lu", fd, (uint64_t) offset, whenceStr, path, ret); return ret; }
qint64 ZoomableAssemblyOverview::minimalOverviewedLen() const { U2OpStatusImpl os; qint64 modelLen = model->getModelLength(os); LOG_OP(os); // 1 letter == 1 pixel. We are not going to draw more than one pixel per letter // Allow more pixels per letter only if model is shorter than screen return qMin(modelLen, (qint64)width()); }
//int dup(int fildes); int posix_dup(const char *path, int fd) { int ret; LOOP_ON_EINTR(ret = dup(fd), ret < 0, errno);; LOG_OP(ret < 0, errno, "dup(fd=%d) path='%s'", fd, path); return ret; }
//int close(int fd); int posix_close(const char *path, int fd) { int ret; LOOP_ON_EINTR(ret = close(fd), ret < 0, errno); LOG_OP(ret < 0, errno, "close(fd=%d) path='%s' ret=%d", fd, path, ret); return ret; }
//int open(char *path, int oflag, mode_t mode); We always use the 3 arguments version int posix_open(const char *path, int oflag, mode_t mode) { int ret; LOOP_ON_EINTR(ret = open(path, oflag, mode), ret < 0, errno); LOG_OP(ret < 0, errno, "open(path='%s' oflag=%#x mode=%#x) ret=%d", path, oflag, mode, ret); return ret; }
//int creat(char *path, mode_t mode); int posix_creat(const char *path, mode_t mode) { int ret; LOOP_ON_EINTR(ret = creat(path, mode), ret < 0, errno); LOG_OP(ret < 0, errno, "creat(path='%s' mode=%#x) ret=%d", path, mode, ret); return ret; }
//DIR *opendir(char *dirname); DIR *posix_opendir(const char *dirname) { DIR *dirp; dirp = opendir(dirname); LOG_OP(dirp == NULL, errno, "opendir(dirname='%s') dirp=%p", dirname, dirp); return dirp; }
//ssize_t write(int fildes, const void *buf, size_t nbyte); ssize_t posix_write(const char *path, int fd, const void *buf, size_t nbyte) { ssize_t ret; LOOP_ON_EINTR(ret = write(fd, buf, nbyte), ret < 0, errno); LOG_OP(ret < 0, errno, "write_packet(fd=%d buf=%p nbyte=%zu) path='%s' ret=%zd", fd, buf, nbyte, path, ret); return ret; }
//int closedir(DIR *dirp); int posix_closedir(const char *path, DIR *dirp) { //this saves the address of the pointer without // keeping and passing the pointer itself to LOG_OP(). ptrdiff_t ptradr = (char *) dirp - (char *) 0; int ret; ret = closedir(dirp); LOG_OP(ret < 0, errno, "closedir(dirp=0x%x) path='%s' ret=%d", ptradr, path, ret); return ret; }
qint64 AssemblyModel::getModelLength(U2OpStatus & os) { if(NO_VAL == cachedModelLength) { // try to set length from attributes U2AttributeDbi * attributeDbi = dbiHandle.dbi->getAttributeDbi(); if(attributeDbi != NULL) { U2IntegerAttribute attr = U2AttributeUtils::findIntegerAttribute(attributeDbi, assembly.id, U2BaseAttributeName::reference_length, os); LOG_OP(os); if(attr.hasValidId()) { cachedModelLength = attr.value; } // ignore incorrect attribute value and remove corrupted attribute (auto-fix incorrectly converted ugenedb) if(cachedModelLength == 0) { coreLog.details(QString("ignored incorrect value of attribute %1: should be > 0, got %2. Bad attribute removed!").arg(QString(U2BaseAttributeName::reference_length)).arg(cachedModelLength)); cachedModelLength = NO_VAL; U2AttributeUtils::removeAttribute(attributeDbi, attr.id, os); } } // if cannot from attributes -> set from reference or max end pos if(cachedModelLength == NO_VAL) { qint64 refLen = hasReference() ? refObj->getSequenceLength() : 0; qint64 assLen = assemblyDbi->getMaxEndPos(assembly.id, os); LOG_OP(os); cachedModelLength = qMax(refLen, assLen); // and save in attribute U2IntegerAttribute attr; U2AttributeUtils::init(attr, assembly, U2BaseAttributeName::reference_length); attr.value = cachedModelLength; attributeDbi->createIntegerAttribute(attr, os); } if(cachedModelLength == NO_VAL){ os.setError("Can't get model length, database is corrupted"); LOG_OP(os); } } return cachedModelLength; }
//int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); int posix_select(const char *path, int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int ret; struct timeval tv; //select() updates timeout which is not permitted by POSIX.1-2001. // So copy the timeout and use the copy in the call. if (timeout != NULL) { tv = *timeout; } LOOP_ON_EINTR(ret = select(nfds, readfds, writefds, exceptfds, (timeout != NULL) ? &tv : NULL), ret < 0, errno); LOG_OP(ret < 0, errno, "select(nfds=%d readfds=%p writefds=%p exceptfds=%p timeout=%ld.%ld) path='%s' ret=%zd", nfds, readfds, writefds, exceptfds, (timeout != NULL) ? timeout->tv_sec : -1, (timeout != NULL) ? timeout->tv_usec : -1, path, ret); return ret; }
const U2AssemblyCoverageStat &AssemblyModel::getCoverageStat(U2OpStatus & os) { QMutexLocker mutexLocker(&mutex); Q_UNUSED(mutexLocker); if(cachedCoverageStat.isEmpty()) { U2AttributeDbi * attributeDbi = dbiHandle.dbi->getAttributeDbi(); if(NULL != attributeDbi) { U2ByteArrayAttribute attr = U2AttributeUtils::findByteArrayAttribute(attributeDbi, assembly.id, COVERAGE_STAT_ATTRIBUTE_NAME, os); if(!os.isCoR()) { if(attr.hasValidId()) { // TODO: check version U2AssemblyUtils::deserializeCoverageStat(attr.value, cachedCoverageStat, os); } else { qint64 length = getModelLength(os); if(!os.isCoR()) { static const qint64 MAX_COVERAGE_CACHE_SIZE = 1000*1000; int coverageCacheSize = (int)qMin(MAX_COVERAGE_CACHE_SIZE, length); cachedCoverageStat.resize(coverageCacheSize); calculateCoverageStat(U2Region(0, length), cachedCoverageStat, os); if(!os.isCoR()) { U2ByteArrayAttribute attribute; attribute.objectId = assembly.id; attribute.name = COVERAGE_STAT_ATTRIBUTE_NAME; attribute.value = U2AssemblyUtils::serializeCoverageStat(cachedCoverageStat); attribute.version = assembly.version; U2OpStatusImpl opStatus; attributeDbi->createByteArrayAttribute(attribute, opStatus); LOG_OP(opStatus); } } } } } else { os.setError("Attribute DBI is not supported"); } } return cachedCoverageStat; }
QString AssemblyBrowser::tryAddObject(GObject * obj) { Document * objDoc = obj->getDocument(); SAFE_POINT(NULL != objDoc, "", tr("Internal error: only object with document can be added to browser")); if (GObjectTypes::SEQUENCE == obj->getGObjectType()) { U2SequenceObject * seqObj = qobject_cast<U2SequenceObject*>(obj); CHECK(NULL != seqObj, tr("Internal error: broken sequence object")); SAFE_POINT(NULL != objDoc->getDocumentFormat(), "", tr("Internal error: empty document format")); U2OpStatus2Log os; qint64 seqLen = seqObj->getSequenceLength(); QStringList errs; qint64 modelLen = model->getModelLength(os); if (seqLen != modelLen) { errs << tr("The lengths of the sequence and assembly are different."); } if (seqObj->getGObjectName() != gobject->getGObjectName()) { errs << tr("The sequence and assembly names are different."); } // commented: waiting for fix //QByteArray refMd5 = model->getReferenceMd5(); //if(!refMd5.isEmpty()) { // //QByteArray data = QString(seqObj->getSequence()).remove("-").toUpper().toUtf8(); // QByteArray data = QString(seqObj->getSequence()).toUpper().toUtf8(); // QByteArray seqObjMd5 = QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex(); // if(seqObjMd5 != refMd5) { // errs << tr("- Reference MD5 not match with MD5 written in assembly"); // } //} bool setRef = !isAssemblyObjectLocked(true) && !model->isLoadingReference(); setRef &= model->checkPermissions(QFile::WriteUser, setRef); if(!errs.isEmpty() && setRef) { const NotificationStack *notificationStack = AppContext::getMainWindow()->getNotificationStack(); const QString message = tr("It seems that sequence \"%1\", set as reference to assembly \"%2\", does not match it.").arg(seqObj->getGObjectName()).arg(gobject->getGObjectName()) + "\n- " + errs.join("\n- "); notificationStack->addNotification(message, Warning_Not); } if(setRef) { model->setReference(seqObj); U2Assembly assembly = model->getAssembly(); U2DataId refId; QString folder; const QStringList folders = model->getDbiConnection().dbi->getObjectDbi()->getObjectFolders(assembly.id, os); if (folders.isEmpty() || os.isCoR()) { folder = U2ObjectDbi::ROOT_FOLDER; } else { folder = folders.first(); } if (seqObj->getEntityRef().dbiRef == model->getDbiConnection().dbi->getDbiRef()) { refId = seqObj->getEntityRef().entityId; } else { U2CrossDatabaseReferenceDbi * crossDbi = model->getDbiConnection().dbi->getCrossDatabaseReferenceDbi(); U2CrossDatabaseReference crossDbRef; // Cannot simply use seqObj->getSequenceRef(), since it points to a temporary dbi // TODO: make similar method seqObj->getPersistentSequenctRef() crossDbRef.dataRef.dbiRef.dbiId = objDoc->getURLString(); crossDbRef.dataRef.dbiRef.dbiFactoryId = "document"; crossDbRef.dataRef.entityId = seqObj->getGObjectName().toUtf8(); crossDbRef.visualName = "cross_database_reference: " + seqObj->getGObjectName(); crossDbRef.dataRef.version = 1; crossDbi->createCrossReference(crossDbRef, folder, os); LOG_OP(os); refId = crossDbRef.id; addObjectToView(obj); } model->associateWithReference(refId); } } else if (GObjectTypes::VARIANT_TRACK == obj->getGObjectType()) { VariantTrackObject *trackObj = qobject_cast<VariantTrackObject*>(obj); CHECK(NULL != trackObj, tr("Internal error: broken variant track object")); model->addTrackObject(trackObj); addObjectToView(obj); connect(model.data(), SIGNAL(si_trackRemoved(VariantTrackObject *)), SLOT(sl_trackRemoved(VariantTrackObject *))); } else {