/*************************************************************************** database.cpp - ------------------- begin : Fri Sep 8 2000 copyright : (C) 2000 by Andrea Rizzi email : rizzi@kde.org ***************************************************************************/ /* Translation search engine Copyright 2000 Andrea Rizzi rizzi@kde.org Copyright 2003 Stanislav Visnovsky visnovsky@kde.org License GPL v 2.0 * * * In addition, as a special exception, the copyright holders give * * permission to link the code of this program with any edition of * * the TQt library by Trolltech AS, Norway (or with modified versions * * of TQt that use the same license as TQt), and distribute linked * * combinations including the two. You must obey the GNU General * * Public License in all respects for all of the code used other than * * TQt. If you modify this file, you may extend this exception to * * your version of the file, but you are not obligated to do so. If * * you do not wish to do so, delete this exception statement from * * your version. * */ #include #include #include #include #include "database.h" #include #include #include #include WordItem::WordItem (char *data, TQString w) { word = w; count = *(uint32 *) data; data += 4; //score=*(int *)data; data += 4; locations = (uint32 *) malloc (4 * count); memcpy (locations, data, 4 * count); } WordItem::WordItem (TQString w) { locations = NULL; count = 0; word = w; score = -1; // it means no references found. } /* WordItem::WordItem(const WordItem &wi) { count=wi.count; score=wi.score; word=wi.word; locations.duplicate(wi.locations); locations.detach(); } WordItem& WordItem::operator=(const WordItem & wi ) { WordItem *i=new WordItem(wi); i->locations.detach(); return *i; } */ bool WordItem::notFound () { return (score == -1); } InfoItem::InfoItem () { catalogName = "No catalog"; lastTranslator = "No translator"; lastFullPath = ""; charset = "No charset"; language = "No language"; } InfoItem::InfoItem (const char *rawData, TQString lang) { const char *rd; rd = rawData; int len; unsigned int secs; // I'll change the charset handling if needed charset = "Utf8"; catalogName = TQString::fromUtf8 (rd); len = strlen (rd) + 1; rd += len; lastTranslator = TQString::fromUtf8 (rd); len = strlen (rd) + 1; rd += len; secs = *(unsigned int *) rd; revisionDate.setTime_t (secs); rd += 4; lastFullPath = TQString::fromUtf8 (rd); len = strlen (rd) + 1; rd += len; language = lang; } void InfoItem::rawData (char *rawData) { char *rd; rd = rawData; strcpy (rd, catalogName.utf8 ()); rd += strlen (rd) + 1; strcpy (rd, lastTranslator.utf8 ()); rd += strlen (rd) + 1; //TQDate Time problem!!!!!!!!!!! TQDateTime zeroDate; zeroDate.setTime_t (0); *(unsigned int *) rd = -revisionDate.secsTo (zeroDate); rd += 4; strcpy (rd, lastFullPath.utf8 ()); rd += strlen (rd) + 1; *rd = 0; //Empty for further info } int InfoItem::size () { int _size; _size = 0; _size += 1; // 1 Empty field; _size += 3; // Terminating \0 of next 3 strings _size += 4; // Int size (date) _size += strlen (catalogName.utf8 ()); _size += strlen (lastTranslator.utf8 ()); _size += strlen (lastFullPath.utf8 ()); return _size; } // this is a quick hack to copy a local file int copy_hack (TQFile & input, TQFile & output) { if (!input.isOpen ()) { if (!input.open (IO_ReadOnly)) return -1; } if (!output.isOpen ()) { if (!output.open (IO_WriteOnly)) return -1; } char buffer[10240]; int s = 0; while (!input.atEnd ()) { s = input.readBlock (buffer, 10240); output.writeBlock (buffer, s); } output.close (); input.close (); return 0; } DataBaseItem::DataBaseItem () { numTra = 0; location = 0; } DataBaseItem::DataBaseItem (char *_key, char *_data) { char *data = _data; key = TQString::fromUtf8 (_key); unsigned int i, r; numTra = *(uint32 *) data; data += 4; location = *(uint32 *) data; data += 4; for (i = 0; i < numTra; i++) { TranslationItem tr; tr.numRef = *(uint32 *) data; data += 4; for (r = 0; r < tr.numRef; r++) { int ref; ref = *(uint32 *) data; data += 4; tr.infoRef.append (ref); } tr.translation = TQString::fromUtf8 ((const char *) data); translations.append (tr); data += strlen (data) + 1; } } uint32 DataBaseItem::sizeKey () { return strlen (key.utf8 ()) + 1; } uint32 DataBaseItem::sizeData () { unsigned int i, _size = 4; _size += numTra * 4; _size += 4; // location for (i = 0; i < numTra; i++) { _size += strlen (translations[i].translation.utf8 ()) + 1; // +1 is for \0 _size += translations[i].numRef * 4; } return _size; } void DataBaseItem::toRawKey (char *_key) { strcpy (_key, key.utf8 ()); } void DataBaseItem::toRawData (char *_data) { char *data = _data; unsigned int i, r; *(uint32 *) data = numTra; data += 4; *(uint32 *) data = location; data += 4; for (i = 0; i < numTra; i++) { TranslationItem tr (translations[i]); *(uint32 *) data = tr.numRef; data += 4; for (r = 0; r < tr.numRef; r++) { *(uint32 *) data = tr.infoRef[r]; //sub i with r data += 4; } strcpy ((char *) data, tr.translation.utf8 ()); data += strlen (tr.translation.utf8 ()) + 1; } } DataBaseManager::DataBaseManager (TQString directory, TQString lang, TQObject * parent, const char *name): TQObject (parent, name) { TQString filename; language = lang; iAmOk = true; basedir = directory; indexDb = wordDb = infoDb = db = 0; openDataBase (); } void DataBaseManager::openDataBase () { kdDebug () << "Opendatabase" << endl; TQString directory; directory = basedir; TQString ll = "." + language; if (ll == ".") ll = ".NOLANG"; TQString transfilename = "%1/translations%2.db"; transfilename = transfilename.arg (directory).arg (ll); TQString infofilename = "%1/catalogsinfo%2.db"; infofilename = infofilename.arg (directory).arg (ll); TQString wordsfilename = "%1/wordsindex%2.db"; wordsfilename = wordsfilename.arg (directory).arg (ll); TQString keysfilename = "%1/keysindex%2.db"; keysfilename = keysfilename.arg (directory).arg (ll); cursor = 0; int ret; if (!db) db_create (&db, 0, 0); db_create (&infoDb, 0, 0); db_create (&wordDb, 0, 0); db_create (&indexDb, 0, 0); ret = db->open (db, #if DB_VERSION_MINOR > 0 NULL, #endif transfilename.local8Bit (), 0, DB_BTREE, 0, 0644); if (ret == DB_OLD_VERSION) { kdDebug (KBABEL_SEARCH) << "Trying upgrade" << endl; // try upgrade KTempFile transFile, infoFile, keysFile, wordsFile; // do the upgrade on the translation file TQFile transfilenameFile (transfilename); if ((ret = copy_hack (transfilenameFile, *transFile.file ())) == 0) { ret = db->upgrade (db, transFile.name ().local8Bit (), 0); } if (ret != 0) { kdDebug (KBABEL_SEARCH) << "Cannot upgrade translations, " << ret << endl; // cleanup transFile.unlink (); iAmOk = false; emit cannotOpenDB (ret); return; } // do the upgrade on the info file TQFile infofilenameFile (infofilename); if ((ret = copy_hack (infofilenameFile, *infoFile.file ())) == 0) { ret = infoDb->upgrade (infoDb, infoFile.name ().local8Bit (), 0); } if (ret != 0) { kdDebug (KBABEL_SEARCH) << "Cannot upgrade catalogsinfo" << endl; // cleanup transFile.unlink (); infoFile.unlink (); iAmOk = false; emit cannotOpenDB (ret); return; } // do the upgrade on the words file TQFile wordfilenameFile (wordsfilename); if ((ret = copy_hack (wordfilenameFile, *wordsFile.file ())) == 0) { ret = wordDb->upgrade (wordDb, wordsFile.name ().local8Bit (), 0); } if (ret != 0) { kdDebug (KBABEL_SEARCH) << "Cannot upgrade words" << endl; // cleanup transFile.unlink (); infoFile.unlink (); wordsFile.unlink (); iAmOk = false; emit cannotOpenDB (ret); return; } // do the upgrade on the keys file TQFile keysfilenameFile (keysfilename); if ((ret = copy_hack (keysfilenameFile, *keysFile.file ())) == 0) { ret = indexDb->upgrade (indexDb, keysFile.name ().local8Bit (), 0); } if (ret != 0) { kdDebug (KBABEL_SEARCH) << "Cannot upgrade keys" << endl; // cleanup transFile.unlink (); infoFile.unlink (); wordsFile.unlink (); keysFile.unlink (); iAmOk = false; emit cannotOpenDB (ret); return; } kdDebug (KBABEL_SEARCH) << "Files upgraded, copying" << endl; // use temporary file instead if (ret == 0) { TDEIO::NetAccess::del (KURL::fromPathOrURL (transfilename)); copy_hack (*transFile.file (), transfilenameFile); transFile.unlink (); TDEIO::NetAccess::del (KURL::fromPathOrURL (infofilename)); copy_hack (*infoFile.file (), infofilenameFile); infoFile.unlink (); TDEIO::NetAccess::del (KURL::fromPathOrURL (wordsfilename)); copy_hack (*wordsFile.file (), wordfilenameFile); wordsFile.unlink (); TDEIO::NetAccess::del (KURL::fromPathOrURL (keysfilename)); copy_hack (*keysFile.file (), keysfilenameFile); keysFile.unlink (); ret = db->open (db, #if DB_VERSION_MINOR > 0 NULL, #endif transfilename.local8Bit (), 0, DB_BTREE, 0, 0644); if (ret != 0) { kdWarning (KBABEL_SEARCH) << "transFilename database can't be opened." << endl; kdWarning (KBABEL_SEARCH) << "Please, report this incident and how to reproduce it to kbabel@kde.org." << endl; iAmOk = false; emit cannotOpenDB (ret); return; } } kdDebug (KBABEL_SEARCH) << "Upgrade done OK" << endl; } // Open catalogs information database ret = infoDb->open (infoDb, #if DB_VERSION_MINOR > 0 NULL, #endif infofilename.local8Bit (), 0, DB_RECNO, 0, 0644); if (ret != 0) { iAmOk = false; emit cannotOpenDB (ret); //Process error here. } else loadInfo (); // Words index database ret = wordDb->open (wordDb, #if DB_VERSION_MINOR > 0 NULL, #endif wordsfilename.local8Bit (), 0, DB_BTREE, 0, 0644); if (ret != 0) { iAmOk = false; emit cannotOpenDB (ret); //Process error here. } //Index of keys. ret = indexDb->open (indexDb, #if DB_VERSION_MINOR > 0 NULL, #endif keysfilename.local8Bit (), 0, DB_RECNO, 0, 0644); if (ret != 0) { iAmOk = false; emit cannotOpenDB (ret); //Process error here. } } void DataBaseManager::closeDataBase () { if (iAmOk) { db->sync (db, 0); db->close (db, 0); infoDb->sync (infoDb, 0); infoDb->close (infoDb, 0); wordDb->sync (wordDb, 0); wordDb->close (wordDb, 0); indexDb->sync (indexDb, 0); indexDb->close (indexDb, 0); // can not be opened again indexDb = wordDb = infoDb = db = 0; } } // I'm not sure this is a good function !!! void DataBaseManager::sync () { // if(iAmOk) // { // db->sync(db,0); // infoDb->sync(infoDb,0); // cursor=0; // } // closeDataBase(); // openDataBase(); db->sync (db, 0); infoDb->sync (infoDb, 0); wordDb->sync (wordDb, 0); indexDb->sync (indexDb, 0); loadInfo (); } DataBaseManager::~DataBaseManager () { closeDataBase (); } int DataBaseManager::putItem (DataBaseItem * item, bool ow) { DBT key, data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); bool ret; uint32 loc = 0; if (item->location == 0) { loc = item->location = appendKey (item->key); // kdDebug(0) << "New key " << item->location << endl; } key.size = item->sizeKey (); data.size = item->sizeData (); key.data = malloc (key.size); data.data = malloc (data.size); item->toRawKey ((char *) key.data); item->toRawData ((char *) data.data); if (ow) ret = db->put (db, 0, &key, &data, 0); else ret = db->put (db, 0, &key, &data, DB_NOOVERWRITE); //check ret if (loc != 0) //I'm new! { uint32 location = loc; TQValueList < TQString > wlist; wlist = wordsIn (item->key); TQValueList < TQString >::Iterator wlistit; for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit) { addLocation (*wlistit, location); } } free (key.data); free (data.data); //READ DOCU !!!! return ret; } DataBaseItem DataBaseManager::getItem (TQString key) { if (!iAmOk) return DataBaseItem (); DBT _key, data; memset (&_key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); int len = strlen (key.utf8 ()); _key.data = malloc (len + 1); _key.size = len + 1; strcpy ((char *) _key.data, key.utf8 ()); int ret; ret = db->get (db, 0, &_key, &data, 0); if (ret != 0) { free (_key.data); return DataBaseItem (); //return an empty database item } DataBaseItem returnItem = DataBaseItem ((char *) _key.data, (char *) data.data); free (_key.data); return returnItem; } DataBaseItem DataBaseManager::cursorGet (uint32 flags) { if (!iAmOk) return DataBaseItem (); int re; DBT key, data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); if (cursor == 0) re = db->cursor (db, 0, &cursor, 0); int ret; if ((ret = cursor->c_get (cursor, &key, &data, flags)) == 0) { return DataBaseItem ((char *) key.data, (char *) data.data); } else { kdDebug (KBABEL_SEARCH) << TQString ("...cursor getting...%1"). arg (ret) << endl; return DataBaseItem (); } } DataBaseItem DataBaseManager::firstItem () { return cursorGet (DB_FIRST); } DataBaseItem DataBaseManager::currentItem () { return cursorGet (DB_CURRENT); } DataBaseItem DataBaseManager::nextItem () { return cursorGet (DB_NEXT); } bool DataBaseManager::isOk () { return iAmOk; } int DataBaseManager::count () { DB_BTREE_STAT *dstat = 0; #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) || (DB_VERSION_MAJOR >= 5) db->stat (db, NULL, &dstat, DB_FAST_STAT); #else db->stat (db, &dstat, DB_FAST_STAT); #endif int ret = dstat->bt_nkeys; free (dstat); return ret; } int DataBaseManager::current () { // THIS FUNCTION SEEM TO NOT WORK (not used) if (!iAmOk) return 0; DBT key, data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); if (cursor != 0) db->cursor (db, 0, &cursor, 0); cursor->c_get (cursor, &key, &data, DB_GET_RECNO); return *(uint32 *) (data.data); } int DataBaseManager::createDataBase (TQString directory, TQString language, int mode) { TQString filename; TQString ll = "." + language; if (ll == ".") ll = ".NOLANG"; filename = "%1/translations%2.db"; filename = filename.arg (directory).arg (ll); rename (filename.local8Bit (), filename.local8Bit () + ",old"); //kdDebug(0) << TQString("Creating %1").arg(filename) << endl; iAmOk = true; int ret; if (!db) { if (db_create (&db, 0, 0) != 0) { kdDebug() << "db_create db failed" << endl; iAmOk = false; return false; } } db->set_flags (db, DB_RECNUM); ret = db->open (db, #if DB_VERSION_MINOR > 0 NULL, #endif filename.local8Bit (), 0, DB_BTREE, DB_CREATE | DB_EXCL, mode); if (ret != 0) { kdDebug() << "db->open " << filename << " " << mode << " failed" << endl; iAmOk = false; } filename = "%1/catalogsinfo%2.db"; filename = filename.arg (directory).arg (ll); rename (filename.local8Bit (), filename.local8Bit () + ",old"); db_create (&infoDb, 0, 0); ret = infoDb->open (infoDb, #if DB_VERSION_MINOR > 0 NULL, #endif filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode); if (ret != 0) iAmOk = false; filename = "%1/wordsindex%2.db"; filename = filename.arg (directory).arg (ll); rename (filename.local8Bit (), filename.local8Bit () + ",old"); db_create (&wordDb, 0, 0); ret = wordDb->open (wordDb, #if DB_VERSION_MINOR > 0 NULL, #endif filename.local8Bit (), 0, DB_BTREE, DB_CREATE, mode); if (ret != 0) iAmOk = false; filename = "%1/keysindex%2.db"; filename = filename.arg (directory).arg (ll); rename (filename.local8Bit (), filename.local8Bit () + ",old"); db_create (&indexDb, 0, 0); ret = indexDb->open (indexDb, #if DB_VERSION_MINOR > 0 NULL, #endif filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode); if (ret != 0) iAmOk = false; if (iAmOk) loadInfo (); else kdDebug (KBABEL_SEARCH) << TQString ("I am NOT ok : %1"). arg (ret) << endl; //THIS IS WRONG, rewrite the error handling. return iAmOk; } InfoItem DataBaseManager::getCatalogInfo (int n) { DBT key; DBT data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); key.data = &n; key.size = 4; //Check for errors int ret = infoDb->get (infoDb, 0, &key, &data, 0); //DB_SET_RECNO); if (ret) { return InfoItem (); } // kdDebug(0) << TQString("Trad %1").arg(ret) << endl; InfoItem it ((char *) data.data, language); //free(data.data); // Read docu for this!!!! return it; } int DataBaseManager::addCatalogInfo (InfoItem * catInfo, int cat = -1) { DBT data; DBT key; // clean up data memset (&data, 0, sizeof (DBT)); memset (&key, 0, sizeof (DBT)); int ret = 0, err; if (cat >= 0) ret = cat; key.size = 4; key.data = &ret; data.size = catInfo->size (); data.data = malloc (data.size); catInfo->rawData ((char *) data.data); // store the catalog data into database if (cat >= 0) err = infoDb->put (infoDb, 0, &key, &data, 0); else err = infoDb->put (infoDb, 0, &key, &data, DB_APPEND); ret = *(int *) key.data; // Append to the list of catalogInfo info.append (*catInfo); // cleanup unneeded data memory free (data.data); return ret; } int DataBaseManager::searchCatalogInfo (TQString location) { int n = 0; TQValueList < InfoItem >::Iterator it; for (it = info.begin (); it != info.end (); ++it) { n++; if ((*it).catalogName == location) return n; } return -1; } bool DataBaseManager::putCatalogInfo (int refnum, InfoItem * catInfo) { DBT data; DBT key; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); int ret; key.size = 4; key.data = &refnum; data.size = catInfo->size (); data.data = malloc (data.size); catInfo->rawData ((char *) data.data); ret = infoDb->put (infoDb, 0, &key, &data, 0); free (data.data); return (ret == 0); } void DataBaseManager::loadInfo () { int nrec; DB_BTREE_STAT *stat; // memset(&stat,0,sizeof(DB_BTREE_STAT)); #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) || (DB_VERSION_MAJOR >= 5) if (infoDb->stat (infoDb, NULL, &stat, DB_FAST_STAT)) fprintf (stderr, "Cannot stat\n"); #else if (infoDb->stat (infoDb, &stat, DB_FAST_STAT)) fprintf (stderr, "Cannot stat\n"); #endif nrec = stat->bt_nkeys; free (stat); info.clear (); for (int i = 1; i <= nrec; i++) // I think DB2 Recno are 1 based. { info.append (getCatalogInfo (i)); } } TQValueList < TQString > DataBaseManager::wordsIn (TQString string) { TQString a; TQValueList < TQString > words; int i, l; a = string.simplifyWhiteSpace (); a = a.stripWhiteSpace (); a = a.lower (); l = a.length (); int c = 0; //words.setAutoDelete(true); //Not sure... check if it is en. TQString m; for (i = 0; i < l; i++) if (a[i].isLetterOrNumber ()) { m += a[i]; } else if (a[i].isSpace ()) { words.append (m); c++; // C++ ;-) m = ""; } words.append (m); return words; } WordItem DataBaseManager::getWordLocations (TQString word) { TQString keystring = word.lower (); DBT key; DBT data; char *keydata; int intlen = strlen (keystring.utf8 ()); keydata = (char *) malloc (intlen + 1); strcpy (keydata, keystring.utf8 ()); memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); key.data = keydata; key.size = intlen + 1; //Check for errors int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); //MAYBE THIS WORD IS NO WHERE!! if (ret) { free (keydata); return WordItem (keystring); } WordItem it ((char *) data.data, keystring); free (keydata); // kdDebug(0) << ((uint32 *)it.locations.data())[0] << endl; return it; } bool DataBaseManager::addLocation (TQString word, unsigned int location) { TQString keystring = word.lower (); DBT key; DBT data; char *keydata; char *newdata; int intlen = strlen (keystring.utf8 ()); keydata = (char *) malloc (intlen + 1); strcpy (keydata, keystring.utf8 ()); memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); key.data = keydata; key.size = intlen + 1; strcpy ((char *) key.data, keystring.utf8 ()); //Check for errors int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); //Check if you get something or not if (ret == 0) // CHANGE IT!!!!! if found something { uint32 *d; d = (uint32 *) data.data; uint32 num = d[0]; uint32 loc = 0; //Position from 0 to num-1 int totalrecord = count (); uint32 step = 1; int antibounce = 0; //d+=4; //int score=d[1]; //d+=4; bool forward, end = false; d[1] = 0; //Before the begin... d += 2; //1 uint32! //Try to guess... loc = location * num / totalrecord + 1; if (loc >= num) loc = num - 1; //Continue if next is smaller or if previous is greater //before the while check if it is ok if (loc == 0) { if (d[loc] > location) end = true; else loc = 1; } if ((loc == num) && !end) { if (d[loc - 1] < location) end = true; else loc = num - 1; } while ((!end) && ((forward = (d[loc]) < location) || ((loc > 0) && (d[loc - 1] > location)))) { antibounce++; //calculate step or use antibounce if (abs ((int) d[loc] - (int) location) < 50 || antibounce > 100) step = 1; //Go linear... else { step = (abs (d[loc] - location) * num) / totalrecord + 1; } kdDebug (KBABEL_SEARCH) << "Insert:" << location << " We are at: " << loc << " i.e. " << d[loc] << " Step:" << step << endl; if (loc > 0) { if (forward) kdDebug (KBABEL_SEARCH) << "Go " << "forward" << " prev is " << d[loc - 1] << endl; else kdDebug (KBABEL_SEARCH) << "Go " << "backward" << " prev is " << d[loc - 1] << endl; } if (forward) { if (loc + step < num) loc += step; // Go forward else loc = num; // Go to num } else { if (loc > step) loc -= step; //Go backward else loc = 0; // Go to 0 } //Now check if I am in the right place [THIS IS NOT NECESSARY] //check if loc and loc -1 are well defined 1 num) loc = num; //Must not happen, idem if (loc == 0) { if (d[loc] > location) end = true; else loc = 1; } if ((loc == num) && !end) { if (d[loc - 1] < location) end = true; else loc = num - 1; } } if (loc == num) kdDebug (KBABEL_SEARCH) << "END" << endl; if (loc == 0) kdDebug (KBABEL_SEARCH) << "BEGIN" << endl; if (loc > 0) kdDebug (KBABEL_SEARCH) << location << " inserted between " << d[loc - 1] << " and " << d[loc] << endl; if ((loc < num && location == d[loc]) || (loc > 0 && location == d[loc - 1])) //What about word repetition { free (keydata); return true; //Why true ?? } //Now insert and put back in the database! newdata = (char *) malloc (4 * (num + 3)); //uint32*(num+score+1..NUM+new) memcpy (newdata, data.data, 4 + 4 + 4 * loc); char *secondpart = (char *) data.data; secondpart += 4 * (loc + 2); memcpy ((newdata + 4 * (loc + 3)), secondpart, (num - loc) * 4); uint32 *intdata = (uint32 *) newdata; intdata[0] = num + 1; //ADD HERE code to recalc score intdata[loc + 2] = location; //ok send it to database! memset (&data, 0, sizeof (DBT)); data.data = newdata; data.size = 4 * (3 + num); } //found sounthing else { //found nothing newdata = (char *) malloc (4 * 3); uint32 *intdata = (uint32 *) newdata; intdata[0] = 1; intdata[1] = 1; intdata[2] = location; memset (&data, 0, sizeof (DBT)); data.data = newdata; data.size = 4 * 3; } memset (&key, 0, sizeof (DBT)); //memset(&data,0,sizeof(DBT)); key.data = keydata; key.size = intlen + 1; ret = wordDb->put (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); free (newdata); free (keydata); //return it; return true; } bool DataBaseManager::removeLocation (TQString /*word */ , int /*location */ ) { //#warning TODO: REMOVE LOCATION return true; } uint32 DataBaseManager::appendKey (TQString _key) { DBT key; DBT data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); uint32 ret = 0, err; key.size = 4; key.data = &ret; data.size = strlen (_key.utf8 ()) + 1; data.data = malloc (data.size); strcpy ((char *) data.data, _key.utf8 ()); err = indexDb->put (indexDb, 0, &key, &data, DB_APPEND); if (err) ret = 0; else ret = *(uint32 *) key.data; //kdDebug(0) << TQString("Append result %1,err = %1").arg(ret).arg(err) << endl; free (data.data); return ret; } TQString DataBaseManager::getKey (uint32 n) { DBT key; DBT data; memset (&key, 0, sizeof (DBT)); memset (&data, 0, sizeof (DBT)); key.data = &n; key.size = 4; //Check for errors int ret = indexDb->get (indexDb, 0, &key, &data, 0); //DB_SET_RECNO); if (ret) return TQString(); return TQString::fromUtf8 ((char *) data.data); // kdDebug(0) << TQString("Trad %1").arg(ret) << endl; } int DataBaseManager::catalogRef (TQString location, TQString author, TQString path) { InfoItem cinfo; int cat, catnum; cat = searchCatalogInfo (location); if (cat == -1) //Not exist { cinfo.catalogName = location; cinfo.lastTranslator = author; cinfo.lastFullPath = path; //TO DO: // //Add date info kdDebug (0) << "New catalog " << endl; catnum = addCatalogInfo (&cinfo); //sync(); kdDebug (0) << "Ref " << catnum << endl; } else { cinfo = getCatalogInfo (cat); //Update date. //last path must be updated cinfo.lastFullPath = path; kdDebug (0) << "New full path " << path << endl; kdDebug (0) << "Ref " << cat << endl; catnum = addCatalogInfo (&cinfo, cat); kdDebug (0) << " must be equal to " << catnum << endl; catnum = cat; } return catnum; } int DataBaseManager::putNewTranslation (TQString key, TQString tran, int catalog, bool ow) { int catnum = catalog; int count = 0; TQString msgid = key; DataBaseItem dbit = getItem (msgid); if (dbit.numTra == 0) //Not found { dbit.numTra += 1; // use local variable, dbit.translations is TQValueList and // will create own copy TranslationItem tra; tra.numRef = 1; tra.translation = tran; tra.infoRef.append (catnum); dbit.translations.append (tra); dbit.key = key; //Check ret value count++; int aa = putItem (&dbit); if (aa) kdDebug (0) << TQString ("-----------put code ") << aa << endl; } else { // key exists TQString msgstr = tran; bool found_catalog_info = false, foundTr = false, isThisOne = false; TQValueList < TranslationItem >::Iterator ittr; bool rem = false; // check all translations in the list for (ittr = dbit.translations.begin (); ittr != dbit.translations.end (); rem ? ittr : ++ittr) { rem = false; found_catalog_info = false; // is the translation one we should put there? isThisOne = (*ittr).translation == msgstr; // is there the catnum we are looking for? if ((*ittr).infoRef.find (catnum) != (*ittr).infoRef.end ()) { found_catalog_info = true; if (ow && !isThisOne) { // I'll look for my catalog reference to del old kdDebug (0) << "Removing the old translation " << endl; (*ittr).numRef -= 1; (*ittr).infoRef.remove (catnum); if ((*ittr).numRef == 0) { dbit.numTra -= 1; // point the iterator to the next valid item ittr = dbit.translations.remove (ittr); rem = true; } } } if (isThisOne) { if (!found_catalog_info) { //There are no reference of this catalog for this translation => add it (*ittr).infoRef.append (catnum); (*ittr).numRef += 1; } foundTr = true; // Ok, we found this translation, no need to add it. } } if (!foundTr) //This translation is new => Add it ! { count++; TranslationItem tra; tra.numRef = 1; tra.translation = msgstr; tra.infoRef.append (catnum); dbit.translations.append (tra); dbit.numTra += 1; } //put the new item in database overwriting the old one. //Check ret value int aa = putItem (&dbit, true); if (aa) kdDebug (0) << TQString ("-----------put code ") << aa << endl; } return count; } void DataBaseManager::rebuildIndexes () { // uint32 loc; #if 0 //Reset the 2 databases here. while (0 /*browse keys here */ ) { loc = item->location = appendKey (item->key); uint32 location = loc; TQValueList < TQString > wlist; wlist = wordsIn (item->key); TQValueList < TQString >::Iterator wlistit; for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit) { addLocation (*wlistit, location); } } #endif } #include "database.moc"