diff -r -u synaptic-0.63clean/common/rpackagecache.h synaptic-0.63cleanPath/common/rpackagecache.h --- synaptic-0.63clean/common/rpackagecache.h 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/common/rpackagecache.h 2010-08-08 19:14:08.000000000 +0200 @@ -51,6 +51,9 @@ inline pkgDepCache *deps() { return _dcache; }; + inline pkgCache *cache() { + return _cache; + }; inline pkgSourceList *list() { return _list; }; diff -r -u synaptic-0.63clean/common/rpackage.cc synaptic-0.63cleanPath/common/rpackage.cc --- synaptic-0.63clean/common/rpackage.cc 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/common/rpackage.cc 2010-08-08 21:05:15.000000000 +0200 @@ -124,6 +124,8 @@ const char *RPackage::summary() { + if(_lister->isAddLoaded()) return getSummaryCache(); + static string _summary; pkgCache::VerIterator ver = (*_depcache)[*_package].CandidateVerIter(*_depcache); @@ -136,9 +138,10 @@ return ""; } - const char *RPackage::maintainer() { + if(_lister->isAddLoaded()) return getMaintainerCache(); + static string _maintainer; pkgCache::VerIterator ver = (*_depcache)[*_package].CandidateVerIter(*_depcache); if (!ver.end()) { @@ -149,6 +152,22 @@ return ""; } +const char *RPackage::description() +{ + if(_lister->isAddLoaded()) return getDescriptionCache(); + + static string _description; + pkgCache::VerIterator ver = (*_depcache)[*_package].CandidateVerIter(*_depcache); + + if (!ver.end()) { + pkgCache::DescIterator Desc = ver.TranslatedDescription(); + pkgRecords::Parser & parser = _records->Lookup(Desc.FileList()); + _description = parseDescription(parser.LongDesc()); + return _description.c_str(); + } else { + return ""; + } +} const char *RPackage::vendor() { @@ -215,20 +234,6 @@ #endif -const char *RPackage::description() -{ - static string _description; - pkgCache::VerIterator ver = (*_depcache)[*_package].CandidateVerIter(*_depcache); - - if (!ver.end()) { - pkgCache::DescIterator Desc = ver.TranslatedDescription(); - pkgRecords::Parser & parser = _records->Lookup(Desc.FileList()); - _description = parseDescription(parser.LongDesc()); - return _description.c_str(); - } else { - return ""; - } -} string RPackage::getRawRecord(bool useCandidateVersion) { diff -r -u synaptic-0.63clean/common/rpackage.h synaptic-0.63cleanPath/common/rpackage.h --- synaptic-0.63clean/common/rpackage.h 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/common/rpackage.h 2010-08-09 03:26:18.000000000 +0200 @@ -93,6 +93,12 @@ pkgCache::PkgIterator *_package; + //cache + string descriptionCache; + string summaryCache; + string maintainerCache; + + // save the default candidate version to undo version selection string _defaultCandVer; @@ -150,6 +156,14 @@ const char *description(); const char *installedFiles(); + const char *getSummaryCache() { return summaryCache.c_str(); } + const char *getMaintainerCache() { return maintainerCache.c_str(); } + const char *getDescriptionCache() { return descriptionCache.c_str(); } + + void setSummaryCache(const string &summaryCache_) { summaryCache = summaryCache_; } + void setMaintainerCache(const string &maintainerCache_) { maintainerCache = maintainerCache_; } + void setDescriptionCache(const string &descriptionCache_) { descriptionCache = descriptionCache_; } + // get changelog file from the debian server string getChangelogFile(pkgAcquire *fetcher); // get screenshot file from the debian server diff -r -u synaptic-0.63clean/common/rpackagelister.cc synaptic-0.63cleanPath/common/rpackagelister.cc --- synaptic-0.63clean/common/rpackagelister.cc 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/common/rpackagelister.cc 2010-08-14 03:36:03.000000000 +0200 @@ -32,11 +32,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "rpackagelister.h" #include "rpackagecache.h" @@ -103,7 +105,6 @@ #ifdef WITH_EPT openXapianIndex(); #endif - if (_viewMode >= _views.size()) _viewMode = 0; _selectedView = _views[_viewMode]; @@ -111,6 +112,18 @@ memset(&_searchData, 0, sizeof(_searchData)); _pkgStatus.init(); + _add_loader = NULL; //off + _add_enabled = true; + _add_loaded = false; + int err; + if((err = pthread_mutex_init(&_add_mutex, 0)) != 0) { + _add_enabled = false; + cerr << "Mutex init error: " << err << endl; + } + if((err = pthread_cond_init(&_add_cond, 0)) != 0) { + _add_enabled = false; + cerr << "Condition init error: " << err << endl; + } cleanCommitLog(); #if 0 @@ -121,8 +134,17 @@ #endif } + RPackageLister::~RPackageLister() { + int err; + if((err = pthread_mutex_destroy(&_add_mutex) != 0)) { + cerr << "Mutex destroy error: " << err << endl; + } + if((err = pthread_cond_destroy(&_add_cond) != 0)) { + cerr << "Condition destroy error: " << err << endl; + } + for (vector::iterator I = _actors.begin(); I != _actors.end(); I++) delete(*I); @@ -130,6 +152,63 @@ delete _cache; } + + +bool RPackageLister::lock(pthread_mutex_t * mutex) { + int err; + if((err = pthread_mutex_lock(mutex)) != 0) { + cerr << "Error mutex lock: " << err << endl; + return false; + } + return true; +} + +bool RPackageLister::unlock(pthread_mutex_t * mutex) { + int err; + if((err = pthread_mutex_unlock(mutex)) != 0) { + cerr << "Error mutex unlock: " << err << endl; + return false; + } + return true; +} + +bool RPackageLister::setAddLoaded() { + if(!lock(&_add_mutex)) return false; + _add_loaded = true; + if(!unlock(&_add_mutex)) return false; + + int err; + if((err = pthread_cond_broadcast(&_add_cond)) != 0) { + cerr << "Error cond broadcast: " << err << endl; + return false; + } +} + +bool RPackageLister::isAddLoaded() { + bool res; + if(!lock(&_add_mutex)) return false; + res = _add_loaded; + if(!unlock(&_add_mutex)) return false; + return res; +} + +bool RPackageLister::waitAddLoaded() { + bool res = true; + + if(!lock(&_add_mutex)) return false; + if(!_add_loaded) { + int err; + if((err = pthread_cond_wait(&_add_cond, &_add_mutex)) != 0) { + cerr << "Error cond wait: " << err << endl; + res = false; + } + } + if(!unlock(&_add_mutex)) return false; + + return res; +} + + void RPackageLister::setView(unsigned int index) { // only save this config if it is not a search @@ -296,6 +375,23 @@ bool RPackageLister::openCache() { + void * ret; + int err; + + //stop addloader + + if(!lock(&_add_mutex)) return false; + _add_enabled = false; + if(!unlock(&_add_mutex)) return false; + + if(_add_loader) { + if((err = pthread_join(*_add_loader, &ret)) != 0) + cerr << "Unable to join add loader: " << err << endl; + delete _add_loader; + _add_loader = NULL; + } + + static bool firstRun = true; if(_config->FindB("Debug::Synaptic::View",false)) @@ -305,11 +401,11 @@ _error->Discard(); // only lock if we run as root - bool lock = true; + bool lockv = true; if(getuid() != 0) - lock = false; + lockv = false; - if (!_cache->open(*_progMeter,lock)) { + if (!_cache->open(*_progMeter,lockv)) { _progMeter->Done(); _cacheValid = false; return _error->Error("_cache->open() failed, please report."); @@ -324,33 +420,27 @@ return _error->Error(_("Internal error opening cache (%d). " "Please report."), 1); } - if (_error->PendingError()) { _cacheValid = false; return _error->Error(_("Internal error opening cache (%d). " "Please report."), 2); } - if (_records) delete _records; _records = new pkgRecords(*deps); - if (_error->PendingError()) { _cacheValid = false; return _error->Error(_("Internal error opening cache (%d). " "Please report."), 3); } - for (vector::iterator I = _packages.begin(); I != _packages.end(); I++) delete (*I); - int packageCount = deps->Head().PackageCount; _packages.resize(packageCount); _packagesIndex.clear(); _packagesIndex.resize(packageCount, -1); - string pkgName; int count = 0; @@ -361,10 +451,8 @@ for (unsigned int i = 0; i != _views.size(); i++) _views[i]->clear(); - pkgCache::PkgIterator I; for (I = deps->PkgBegin(); I.end() != true; I++) { - if (I->CurrentVer != 0) _installedCount++; else if (I->VersionList == 0) @@ -406,26 +494,160 @@ // Truncate due to virtual packages which were skipped above. _packages.resize(count); - // refresh the views for (unsigned int i = 0; i != _views.size(); i++) _views[i]->refresh(); applyInitialSelection(); - _updating = false; reapplyFilter(); - // mvo: put it here for now notifyCacheOpen(); firstRun = false; - _cacheValid = true; + + + //start addloader + if(!lock(&_add_mutex)) return false; + _add_enabled = true; + if(!unlock(&_add_mutex)) return false; + + pthread_attr_t attr; + if((err = pthread_attr_init(&attr)) != 0) { + cerr << "Unable to set attr: " << err << endl; + return _error->Error(_("Internal loader error."), err); + } + if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) != 0) { + cerr << "Unable to set detachstate: " << err << endl; + return _error->Error(_("Internal loader error."), err); + } + _add_loader = new pthread_t; + if((err = pthread_create(_add_loader, &attr, addloader, (void *) this)) != 0) { + cerr << "Unable to pthread create: " << err << endl; + return _error->Error(_("Internal loader error."), err); + } + + return true; +} + +// LocalitySort - Sort a version list by package file locality /*{{{*/ +// --------------------------------------------------------------------- + +bool LocalityCompare(const void * a, const void * b) { + pkgCache::VerFile *A = (pkgCache::VerFile *) a; + pkgCache::VerFile *B = (pkgCache::VerFile *) b; + + if (A == 0 && B == 0) + return false; + if (A == 0) + return true; + if (B == 0) + return false; + + if (A->File == B->File) + return A->Offset < B->Offset; + return A->File < B->File; +} + +void * addloader(void * arg) { + // load package descriptions and vendors + + RPackageLister *_lister = (RPackageLister *) arg; + + pkgCache &Cache = *(_lister->cache()->cache()); + pkgDepCache::Policy Plcy; + pkgRecords Recs(Cache); + if (_error->PendingError() == true) { + _error->Error(_("Internal loader error.")); + return 0; + } + + bool enabled = true; + + //get file pointers + vector dfs; + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false && enabled; I++) { + // Find the proper version to use. + pkgCache::VerIterator V = Plcy.GetCandidateVer(I); + if (V.end() == false) { + dfs.push_back(V.DescriptionList().FileList()); + } + } + + sort(dfs.begin(), dfs.end(), LocalityCompare); + + for(vector::iterator dI = dfs.begin(); dI != dfs.end(); dI++) { + pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache, *dI)); + RPackage * pkg = _lister->getPackage(P.Name()); + + if(!_lister->lock()) return 0; + enabled = _lister->getAddLoaderEnabled(); + if(enabled) { + pkg->setSummaryCache(P.ShortDesc()); + pkg->setMaintainerCache(P.Maintainer()); + pkg->setDescriptionCache(P.LongDesc()); + } + if(!_lister->unlock()) return 0; + } + + _lister->setAddLoaded(); + + nice(-19); + + //cache package database (.list files needed by dpkg) + + vector files; + if(!get_files("/var/lib/dpkg/info", ".list", files)) return 0; + for(vector::const_iterator fit = files.begin(); fit != files.end(); ++fit) { + bool enabled; + if(!_lister->lock()) return 0; + enabled = _lister->getAddLoaderEnabled(); + if(!_lister->unlock()) return 0; + + if(!enabled) return 0; + + read_file(string("/var/lib/dpkg/info/") + *fit, 512); + } + + return 0; +} + + +bool get_files(const string &dir, const string &suffix, vector &files) { + DIR *dp; + struct dirent *dirp; + if ((dp = opendir(dir.c_str())) == NULL) { + cerr << "Error(" << errno << ") opening " << dir << endl; + return false; + } + + while ((dirp = readdir(dp)) != NULL) { + string name = string(dirp->d_name); + if(name.length() < suffix.length()) continue; + if(name.substr(name.length() - suffix.length(), suffix.length()) == suffix) + files.push_back(name); + } + closedir(dp); return true; } + +void read_file(const string &file_name, int block_size) { + ifstream file; + file.open(file_name.c_str(), ios::in | ios::binary); + if (file.is_open()) { + char * memblock = new char[block_size]; + while (!file.eof()) { + file.read(memblock, block_size); + } + file.close(); + delete[] memblock; + } +} + + #ifdef WITH_EPT bool RPackageLister::xapianIndexNeedsUpdate() { @@ -572,7 +794,6 @@ if(_config->FindB("Debug::Synaptic::View",false)) clog << "RPackageLister::reapplyFilter()" << endl; - _selectedView->refresh(); _viewPackages.clear(); _viewPackagesIndex.clear(); _viewPackagesIndex.resize(_packagesIndex.size(), -1); @@ -1458,7 +1679,7 @@ string errm = (*I)->ErrorText; ostringstream tmp; // TRANSLATORS: Error message after a failed download. - // The first %s is the URL and the second + // The first %s is the URL and the second // one is a detailed error message that // is provided by apt ioprintf(tmp, _("Failed to fetch %s\n %s\n\n"), @@ -1752,11 +1973,6 @@ return true; } -void RPackageLister::refreshView() -{ - _selectedView->refresh(); -} - bool RPackageLister::writeSelections(ostream &out, bool fullState) { for (unsigned i = 0; i < _packages.size(); i++) { diff -r -u synaptic-0.63clean/common/rpackagelister.h synaptic-0.63cleanPath/common/rpackagelister.h --- synaptic-0.63clean/common/rpackagelister.h 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/common/rpackagelister.h 2010-08-10 23:38:12.000000000 +0200 @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef WITH_EPT #include @@ -105,6 +106,16 @@ }; +// LocalitySort - Sort a version list by package file locality /*{{{*/ +// --------------------------------------------------------------------- + +bool LocalityCompare(const void * a, const void * b); + +void * addloader(void * arg); //additional info thread loader +bool get_files(const string &dir, const string &suffix, vector &files); +void read_file(const string &file, int block_size); + + class RPackageLister { protected: @@ -141,11 +152,20 @@ RPackageViewFilter *_filterView; // the package view that does the filtering RPackageViewSearch *_searchView; // the package view that does the (simple) search + //additional package info loader (description, symmary, maintainer + pthread_t * _add_loader; + pthread_cond_t _add_cond; + pthread_mutex_t _add_mutex; + bool _add_enabled; //thread can run + bool _add_loaded; + // helper for the limitBySearch() code static const int defaultQualityCutoff = 15; bool xapianSearch(string searchString); - public: +public: + + RPackageCache * cache() { return _cache; } unsigned int _viewMode; @@ -211,7 +231,27 @@ list undoStack; list redoStack; - public: + bool lock(pthread_mutex_t * mutex); + bool unlock(pthread_mutex_t * mutex); + +public: + + bool isCacheToReset() { + return _updating; + } + + bool getAddLoaderEnabled() { + return _add_enabled; + } + + bool lock() { return lock(&_add_mutex); } + bool unlock() { return unlock(&_add_mutex); } + + //additional package info load + bool setAddLoaded(); + bool isAddLoaded(); + bool waitAddLoaded(); + // limit what the current view displays bool limitBySearch(string searchString); @@ -232,9 +272,6 @@ // this needs a different name, something like refresh void reapplyFilter(); - // refresh view - void refreshView(); - // is is exposed for the stuff like filter manager window RPackageViewFilter *filterView() { return _filterView; }; RPackageViewSearch *searchView() { return _searchView; }; @@ -306,6 +343,7 @@ bool cleanPackageCache(bool forceClean = false); bool updateCache(pkgAcquireStatus *status, string &error); bool commitChanges(pkgAcquireStatus *status, RInstallProgress *iprog); + void commitPackageStates(); // some information bool getDownloadUris(vector &uris); diff -r -u synaptic-0.63clean/gtk/rgmainwindow.cc synaptic-0.63cleanPath/gtk/rgmainwindow.cc --- synaptic-0.63clean/gtk/rgmainwindow.cc 2010-05-04 17:20:15.000000000 +0200 +++ synaptic-0.63cleanPath/gtk/rgmainwindow.cc 2010-08-11 01:24:10.000000000 +0200 @@ -103,61 +103,32 @@ void RGMainWindow::changeView(int view, string subView) { + _blockActions = TRUE; + if(_config->FindB("Debug::Synaptic::View",false)) ioprintf(clog, "RGMainWindow::changeView(): view '%i' subView '%s'\n", - view, subView.size() > 0 ? subView.c_str() : "(empty)"); + view, subView.size() > 0 ? subView.c_str() : "(empty)"); if(view >= N_PACKAGE_VIEWS) { //cerr << "changeView called with invalid view NR: " << view << endl; view=0; } - _blockActions = TRUE; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_viewButtons[view]), TRUE); + //this->setBusyCursor(true); // we need to set a empty model first so that gtklistview // can do its cleanup, if we do not do that, then the cleanup // code in gtktreeview gets confused and throws // Gtk-CRITICAL **: gtk_tree_view_unref_tree_helper: assertion `node != NULL' failed // at us, see LP: #38397 for more information - gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView), NULL); - - RPackage *pkg = selectedPackage(); + gtk_tree_view_set_model(GTK_TREE_VIEW(this->_treeView), NULL); - _lister->setView(view); + _lister->setView(view); + this->refreshTable(NULL, false); refreshSubViewList(); - - GtkTreeSelection* selection; - setBusyCursor(true); - setInterfaceLocked(TRUE); - GtkWidget *tview = glade_xml_get_widget(_gladeXML, "treeview_subviews"); - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tview)); - if(!subView.empty()) { - GtkTreeModel *model; - GtkTreeIter iter; - char *str; - - model = gtk_tree_view_get_model(GTK_TREE_VIEW(tview)); - if(gtk_tree_model_get_iter_first(model, &iter)) { - do { - gtk_tree_model_get(model, &iter, 0, &str, -1); - if(strcoll(str, MarkupEscapeString(subView).c_str()) == 0) { - gtk_tree_selection_select_iter(selection, &iter); - break; - } - } while(gtk_tree_model_iter_next(model, &iter)); - } - } else { - GtkTreePath * path = gtk_tree_path_new_from_string( "0" ); - gtk_tree_selection_select_path( selection, path ); - } - _lister->setSubView(subView); - refreshTable(pkg,false); - setInterfaceLocked(FALSE); - setBusyCursor(false); _blockActions = FALSE; - setStatusText(); } void RGMainWindow::refreshSubViewList() @@ -515,7 +486,6 @@ me->_lister->unregisterObserver(me); me->_lister->getCache()->deps()->MarkAndSweep(); - me->_lister->refreshView(); me->_lister->registerObserver(me); me->refreshTable(); @@ -654,7 +624,6 @@ vector instPkgs; RPackage *pkg = NULL; int flags; - while (li != NULL) { pkgDepCache::ActionGroup group(*_lister->getCache()->deps()); gtk_tree_model_get_iter(_pkgList, &iter, (GtkTreePath *) (li->data)); @@ -722,7 +691,6 @@ _lister->notifyCachePostChange(); bool changed = askStateChange(state, exclude); - if (changed) { bool failed=false; // check for failed installs, if a installs fails, restore old state @@ -784,7 +752,7 @@ } RGMainWindow::RGMainWindow(RPackageLister *packLister, string name) - : RGGladeWindow(NULL, name), _lister(packLister), _pkgList(0), + : RGGladeWindow(NULL, name), _lister(packLister), _pkgList(0), _treeView(0), _tasksWin(0), _iconLegendPanel(0), _pkgDetails(0), _logView(0), _installProgress(0), _fetchProgress(0), _fastSearchEventID(-1) @@ -2003,7 +1971,7 @@ assert(me); // Ignore DEL accelerator when fastsearch has focus GtkWidget *entry = glade_xml_get_widget(me->_gladeXML, "entry_fast_search"); - if (gtk_widget_has_focus (entry) && GPOINTER_TO_INT(data) == PKG_DELETE) { + if (GTK_WIDGET_HAS_FOCUS (entry) && GPOINTER_TO_INT(data) == PKG_DELETE) { return; } me->pkgAction((RGPkgAction)GPOINTER_TO_INT(data)); @@ -2476,6 +2444,26 @@ searchProgress); me->changeView(PACKAGE_VIEW_SEARCH, str); + + // we auto set to last search + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + char *buff; + + GtkWidget *view = glade_xml_get_widget(me->_gladeXML, "treeview_subviews"); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); + if (gtk_tree_model_get_iter_first(model, &iter)) { + do { + gtk_tree_model_get(model, &iter, 0, &buff, -1); + if (strcoll(buff, str.c_str()) == 0) { + gtk_tree_selection_select_iter(selection, &iter); + break; + } + } while (gtk_tree_model_iter_next(model, &iter)); + } + me->setBusyCursor(false); gchar *statusstr = g_strdup_printf(_("Found %i packages"), found); me->setStatusText(statusstr); @@ -2825,7 +2813,6 @@ return; } } - me->setInterfaceLocked(TRUE); me->updatePackageInfo(NULL); @@ -2881,9 +2868,11 @@ #endif // HAVE_RPM me->_installProgress = dynamic_cast(iprogress); + //bool result = me->_lister->commitChanges(fprogress, iprogress); me->_lister->commitChanges(fprogress, iprogress); + // FIXME: move this into the terminal class #ifdef HAVE_TERMINAL // wait until the term dialog is closed @@ -2923,6 +2912,7 @@ exit(1); } } + // reread saved selections ifstream in(file); if (!in != 0) { @@ -2934,7 +2924,6 @@ unlink(file); g_free((void *)file); - me->setTreeLocked(FALSE); me->refreshTable(); me->refreshSubViewList();