/** * Stats the given file. If <tt>throttleRate</tt> seconds have passed since * the last time stat() was called on this file, then the file will be * re-stat()ted, otherwise the cached stat information will be returned. * * @param filename The file to stat. * @param stat A pointer to a stat struct; the retrieved stat information * will be stored here. * @param throttleRate Tells this CachedFileStat that the file may only * be statted at most every <tt>throttleRate</tt> seconds. * @return 0 if the stat() call succeeded or if the cached stat information was used; * -1 if something went wrong while statting the file. In the latter * case, <tt>errno</tt> will be populated with an appropriate error code. * @throws SystemException Something went wrong while retrieving the * system time. stat() errors will <em>not</em> result in * SystemException being thrown. * @throws boost::thread_interrupted */ int stat(const string &filename, struct stat *buf, unsigned int throttleRate = 0) { boost::unique_lock<boost::mutex> l(lock); EntryMap::iterator it(cache.find(filename)); EntryPtr entry; int ret; if (it == cache.end()) { // Filename not in cache. // If cache is full, remove the least recently used // cache entry. if (maxSize != 0 && cache.size() == maxSize) { EntryList::iterator listEnd(entries.end()); listEnd--; string filename((*listEnd)->filename); entries.pop_back(); cache.erase(filename); } // Add to cache as most recently used. entry = EntryPtr(new Entry(filename)); entries.push_front(entry); cache[filename] = entries.begin(); } else { // Cache hit. entry = *it->second; // Mark this cache item as most recently used. entries.erase(it->second); entries.push_front(entry); cache[filename] = entries.begin(); } ret = entry->refresh(throttleRate); *buf = entry->info; return ret; }
/** * Creates a complete set of positioned label nodes from a feature list. */ osg::Node* createNode( const FeatureList& input, const Style& style, const FilterContext& context ) { const TextSymbol* text = style.get<TextSymbol>(); if ( !text ) return 0L; osg::Group* group = new osg::Group(); Decluttering::setEnabled( group->getOrCreateStateSet(), true ); if ( text->priority().isSet() ) { DeclutteringOptions dco = Decluttering::getOptions(); dco.sortByPriority() = text->priority().isSet(); Decluttering::setOptions( dco ); } StringExpression contentExpr ( *text->content() ); NumericExpression priorityExpr( *text->priority() ); if ( text->removeDuplicateLabels() == true ) { // in remove-duplicates mode, make a list of unique features, selecting // the one with the largest area as the one we'll use for labeling. typedef std::pair<double, osg::ref_ptr<const Feature> > Entry; typedef std::map<std::string, Entry> EntryMap; EntryMap used; for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i ) { Feature* feature = i->get(); if ( feature && feature->getGeometry() ) { const std::string& value = feature->eval( contentExpr ); if ( !value.empty() ) { double area = feature->getGeometry()->getBounds().area2d(); if ( used.find(value) == used.end() ) { used[value] = Entry(area, feature); } else { Entry& biggest = used[value]; if ( area > biggest.first ) { biggest.first = area; biggest.second = feature; } } } } } for( EntryMap::iterator i = used.begin(); i != used.end(); ++i ) { const std::string& value = i->first; const Feature* feature = i->second.second.get(); group->addChild( makeLabelNode(context, feature, value, text, priorityExpr) ); } } else { for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i ) { const Feature* feature = i->get(); if ( !feature ) continue; const Geometry* geom = feature->getGeometry(); if ( !geom ) continue; const std::string& value = feature->eval( contentExpr, &context ); if ( value.empty() ) continue; group->addChild( makeLabelNode(context, feature, value, text, priorityExpr) ); } } #if 0 // good idea but needs work. DepthOffsetGroup* dog = new DepthOffsetGroup(); dog->setMinimumOffset( 500.0 ); dog->addChild( group ); return dog; #endif return group; }
/** * Returns whether <tt>filename</tt> is in the cache. */ bool knows(const string &filename) const { boost::unique_lock<boost::mutex> l(lock); return cache.find(filename) != cache.end(); }