⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qwsdatabase.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }    unsigned char test = 0;    while(!dbfile->atEnd()) {	test = dbfile->getch();	uint size = readUint();	bool failed = FALSE;	switch(test) {	    case type_record:		if (i)		    i->insertDirect(readRecord(offset), offset);		break;	    case type_free:	    case type_unknown:		if (recoverFreeLists) {		    if (!eraseRecord(offset, TRUE))			stillErrors = TRUE;		}		break;	    default: // covers test_invalid.		// something has gone wrong, stop reading		if (truncate) {		    Global::truncateFile(dbfile->handle(), offset);		    dbfile->flush();		    d->dbend = offset;		} else {		    qWarning("WARNING, data inconsistency found, "			    "invalid element found while parsing records");		}		failed = TRUE;		break;	}	if (failed)	    break;	offset += size + 1 + sizeof(uint);	dbfile->at(offset);    }}/*!  Adds a new index \a i to the database.*/void QWSDatabase::addIndex(QWSDatabaseIndex* i){    d->indices.append(i);}/*!  Removes index \a i from the database.*/void QWSDatabase::removeIndex(QWSDatabaseIndex* i){    d->indices.removeRef(i);}void QWSDatabase::removeRecordAt(uint pos, QWSDatabaseIndex* skip){    d->unindexify(pos,skip,this);    if ( !skip )	eraseRecord( pos );}/*!  Returns the record at offset \a pos in the database file.  */QByteArray QWSDatabase::atOffset(uint pos) const{    return readRecord(pos);}/*!  Sets indexing.  If \a b is TRUE then all elements in the database  will be inserted into the index, the order of elements being maintained.  Otherwise elements inserted into the database will not be added to the  index.*/void QWSDatabase::setIndexing(bool b){    if (d && d->indexed != b ) {	d->indexed = b;	if (b)	    reindex();    }}/*!  Returns TRUE if the database is currently adding new items to the indexs.  Otherwise returns FALSE.*/bool QWSDatabase::indexing() const{    if (d)	return d->indexed;    return FALSE;}/*!  Returns the name of the attribute \a attr.*/QString QWSDatabase::attributeName(int attr) const{    if (!d)	return QString::null;    QString* s = d->keys[attr];    return s ? *s : QString::null;}/*!  Returns the index of the attribute \a attr.*/int QWSDatabase::attribute(const QString &attr) const{    if (!d)	return -1;    QIntDictIterator<QString> it( d->keys ); // See QIntDictIterator    for ( ; it.current(); ++it )	if(!qstrcmp(*(it.current()), attr))	    return it.currentKey();    return -1;}/*!  Adds a new attribute to the database with name \a attr at position  \a id.*/void QWSDatabase::addAttribute(int id, const QString &attr){    if(!d)	return;    d->keys.replace(id, new QString(attr));}/*!  \internal  used to read a uint from the database.*/uint QWSDatabase::readUint() const{    uint v = 0;    v += dbfile->getch();    v <<= 8;    v += dbfile->getch();    v <<= 8;    v += dbfile->getch();    v <<= 8;    v += dbfile->getch();    return v;}/* return false on failure */bool QWSDatabase::writeUint(uint v){    uint mask = 0x000000FF;    bool success = TRUE;    if (dbfile->putch(v >> 24 & mask) == -1)	success = FALSE;    if (dbfile->putch(v >> 16 & mask) == -1)	success = FALSE;    if (dbfile->putch(v >> 8 & mask) == -1)	success = FALSE;    if (dbfile->putch(v & mask) == -1)	success = FALSE;    return success;}/*!  \internal  Attempts to write \a value at \a offset in the database file.  If an error  occurs the database will pop a warning querying the user if they want  to retry or cancel the write.*/bool QWSDatabase::attemptWriteUint(uint offset, uint value){    while (1) {	dbfile->resetStatus();	dbfile->at(offset);	writeUint(value);	dbfile->flush();	if (dbfile->status() == IO_Ok)	    break;	if (recoverableError() == 1)	    return FALSE;    }    return TRUE;}/*!  \internal  Attempts to write \a size bytes of \a data at \a offset in the   database file.  If an error occurs the database will pop a warning   querying the user if they want to retry or cancel the write.*/bool QWSDatabase::attemptWriteBlock(uint offset, const char *data, uint size) {    dbfile->resetStatus();    while (1) {	dbfile->at(offset);	dbfile->writeBlock(data, size);	dbfile->flush();	if (dbfile->status() == IO_Ok)	    break;	if (recoverableError() == 1)	    return FALSE;	dbfile->resetStatus();    }    return TRUE;}/*!  \internal  This is a very important function.  It attempts (just once) to  write the block type \a t into the   database file.  If an error occurs the database will pop a warning   indicate that an unrecoverable error has occurred.  The operation cannot  be completed.*/bool QWSDatabase::attemptSetBlockType(unsigned char t) {    dbfile->resetStatus();    dbfile->putch(t);    dbfile->flush();    if (dbfile->status() != IO_Ok) {	unrecoverableError(); // tell the user	return FALSE;    }    return TRUE;}void QWSDatabase::updateDirtCount(){    // now update the dirtCount;    dirty++;    dbfile->at(0);    writeUint(dirty);    dbfile->flush();    // this is at the start of the file.  IF this fails, I don't     // think we can recover.}/*!  Attempts to write record \a r into the database.  If successful, returns   the offset where the record was written.  Otherwise returns 0.    \sa readRecord(), eraseRecord */uint QWSDatabase::writeRecord(const QByteArray &r){    QByteArray ba = r;    uint real_size = ba.size() + 1 + sizeof(uint);    /* ba now contains the data (and records it size) */    /* first check the free lists */    uint list_num = 0;    do {	if (		(d->freelists[list_num].count > 0)		&&		(d->freelists[list_num].size >= real_size)	   )	    break;	list_num++;    } while(list_num < number_lists);    if (list_num == number_lists)	list_num--;    // list num is now the list with size just larger than real_size.    // (or is the last list    uint offset;    uint size = 0;    Q_UINT32 next = 0;    if (d->freelists[list_num].count > 0) {	// search the free list for the right size (first fit).	offset = d->freelists[list_num].start;	uint last = 0;	uint count = d->freelists[list_num].count;	bool found_gap = FALSE;	while(count--) {	    dbfile->at(offset);	    	    unsigned char test = 0;	    test = dbfile->getch();	    if(test != type_free) {		qWarning("WARNING, data inconsistency found, free list element wasn't");		//recordError(test);  // future		break; // no free list found	    }	    size = readUint();	    next = readUint();	    if (size >= ba.size()) {		if (last) {		    dbfile->at(last);		    if (!attemptSetBlockType(type_unknown))			return 0; // no harm done, yet		    if (!attemptWriteUint(last + 1 + sizeof(uint), next))			return 0;		    dbfile->at(last);		    if (!attemptSetBlockType(type_free))			return 0; // harm done, but can fix later		} else {		    d->freelists[list_num].start = next;		}		ba.resize(size); // so erase gets the right amount of space		d->freelists[list_num].count -= 1;		found_gap = TRUE;		break;	    } else {		last = offset;		offset = next;	    }	}	if (found_gap) {	    dbfile->at(offset);	    if (!attemptSetBlockType(type_unknown))		return 0; 	    if (!attemptWriteBlock(offset + 1 + sizeof(uint),			ba.data(), size))		return 0;  // harm done but we will recover	    // mark as record	    dbfile->at(offset);	    if (!attemptSetBlockType(type_record))		return 0; // record is there... but we can't touch it.	    updateDirtCount();	    return offset;	}    }    // failed to find offset for whatever reason     offset = d->dbend;    d->dbend = offset + real_size;        dbfile->at(offset);    if (!attemptSetBlockType(type_invalid))	return 0;    if (!attemptWriteUint(offset + 1, ba.size()))	return 0;    if (!attemptWriteBlock(offset + 1 + sizeof(uint), ba.data(), ba.size()))	return 0;    // mark as record.    dbfile->at(offset);    if (!attemptSetBlockType(type_record))	return 0;    updateDirtCount();    return offset;}/*!  Attempts to read a record from the database.  If successful, returns   the record at \a offset.  Otherwise returns a the default record  empty ByteArray.    \sa writeRecord(), eraseRecord*/QByteArray QWSDatabase::readRecord(uint offset) const{    QByteArray ba;    dbfile->at(offset);    char test = dbfile->getch();    if (test != type_record) {	//qWarning("WARNING, data inconsistency found, record element wasn't a record");	return QByteArray();  // no record here    }    uint size = readUint();    ba.resize(size);    dbfile->readBlock(ba.data(), size);    return QByteArray(ba);}/*!  Attempts to erase whatever is at \a offset in the database file.  If  \a ignore_type is FALSE then will fail if \a offset is not the beginning  of a record.  This function will return FALSE if there was an error in erasing the  record.  This doesn't indicate that the record wasn't erased, but rather  that it is indeterminate whether the record was erased.  If the record  was successfully erased the function returns TRUE.    \sa writeRecord(), readRecord*/bool QWSDatabase::eraseRecord(uint offset, bool ignore_type){    if(offset > d->dbend)	return FALSE;    dbfile->at(offset);    unsigned char test = dbfile->getch();    if (test == type_invalid || (!ignore_type && test != type_record)) {	qWarning("WARNING, data inconsistency found record marked" 		" for deletion not a record.");	return FALSE; // um, shouldn't erase something that isn't a record.    }    QDataStream ds(dbfile);    uint orig_size = readUint();    // logic in writeRecord attempts to assure this will always be a    // multiple of smallest_list;    uint erase_size = orig_size + 1 + sizeof(uint);    /* do what is needed to mark this record as erased */    if (offset + erase_size >= d->dbend) {	Global::truncateFile(dbfile->handle(), offset);	dbfile->flush();	d->dbend = offset;	return TRUE;    }    uint list_num = 0;    do {	if (		(d->freelists[list_num].count > 0)		&&		(d->freelists[list_num].size >= erase_size)	   )	    break;	list_num++;    } while(list_num < number_lists);    if (list_num == number_lists)	list_num--;    // list num is now the list with size just larger than real_size.    // (or is the last list    dbfile->at(offset);    if (!attemptSetBlockType(type_unknown))	return FALSE; // we haven't modified anything yet.    if (!attemptWriteUint(offset + 1 + sizeof(uint), 		d->freelists[list_num].start))	return FALSE; // its an unknonw block now, can fix later.    // we assume this succeeds, no failure if it doesn't    // now 0 out remaining space    for (uint i = 0; i < (orig_size - 4); i++)	dbfile->putch(0);    dbfile->flush();    dbfile->at(offset);    if (!attemptSetBlockType(type_free))	return FALSE; // we haven't modified anything yet.    d->freelists[list_num].count += 1;    d->freelists[list_num].start = offset;    updateDirtCount();    return TRUE;}void QWSDatabase::reindex(){    d->reindex();}/*!  Returns the dirt count of the database.  This is useful for classes  that store separate data to be sure they are still in sync with the database.*/uint QWSDatabase::dirtCount() const{    return dirty;}void QWSDatabase::writeHeader(){    hdrfile->open(IO_WriteOnly);    QDataStream ds(hdrfile);    ds << dirty;    ds << d->dbend;    uchar key_count = d->keys.count();    ds << key_count;    QIntDictIterator<QString> it( d->keys ); // See QIntDictIterator    for ( ; it.current(); ++it ) {	uchar key = it.currentKey();	const char *name = it.current()->utf8();	ds << key;	ds << name;    }    // the free lists    uint ui;    for(ui = 0; ui < number_lists; ui++) {	ds << d->freelists[ui].start;	ds << d->freelists[ui].count;    }    hdrfile->close();}bool QWSDatabase::readHeader(){    if (!d)	return FALSE;    if (!hdrfile->exists()) {	d->dbend = 4; // after all first 4 bytes are a dirtcount	// everything else is initialized already, or at least should be.	writeHeader();    } else {	hdrfile->open(IO_ReadOnly);	QDataStream ds(hdrfile);	uint tmp_dirty;	ds >> tmp_dirty;	if (tmp_dirty != dirty) {	    /* some problem has occurred in storing the header.	       Attempt to recover the free lists */	    recover(0, TRUE, TRUE);	    hdrfile->close();	    return TRUE;	}	d->dbend = 0;	ds >> d->dbend;	uchar key_count = 0;	ds >> key_count;	while(key_count-- > 0) {	    uchar key = 0;	    char *keyName;	    ds >> key;	    ds >> keyName;	    d->keys.replace(key, new QString(QString::fromUtf8(keyName)));	}	for(uint i = 0; i < number_lists; i++) {	    uint start = 0;	    uint end = 0;	    ds >> start;	    ds >> end;	    d->freelists[i].start = start;	    d->freelists[i].count = end;	}	hdrfile->close();    }    return TRUE;}int QWSDatabase::recoverableError() const{    // FIXME This message probably needs to say more to the user.    return QMessageBox::critical(0, tr("Could not write data."), 	    tr("Could not write data."), tr("retry"), tr("cancel"));}void QWSDatabase::unrecoverableError() const{    // FIXME This message probably needs to say more to the user.    QMessageBox::critical(0, tr("Fatal Storage Error"), 	    tr("Could not write data."), tr("cancel"));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -