<commit_before>#pragma once

#include <leveldb/cache.h>
#include <leveldb/comparator.h>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>

#include <bts/db/exception.hpp>
#include <bts/db/upgrade_leveldb.hpp>

#include <fc/filesystem.hpp>
#include <fc/io/json.hpp>
#include <fc/io/raw.hpp>
#include <fc/reflect/reflect.hpp>

#include <fstream>

namespace bts { namespace db {

  namespace ldb = leveldb;

  /**
   *  @brief implements a high-level API on top of Level DB that stores items using fc::raw / reflection
   */
  template<typename Key, typename Value>
  class level_map
  {
     public:
        void open( const fc::path& dir, bool create = true, size_t cache_size = 0 )
        { try {
           FC_ASSERT( !is_open(), "Database is already open!" );

           ldb::Options opts;
           opts.comparator = &_comparer;
           opts.create_if_missing = create;
           opts.max_open_files = 64;
           opts.compression = leveldb::kNoCompression;

           if( cache_size > 0 )
           {
               opts.write_buffer_size = cache_size / 4; // up to two write buffers may be held in memory simultaneously
               _cache.reset( leveldb::NewLRUCache( cache_size / 2 ) );
               opts.block_cache = _cache.get();
           }

           if( ldb::kMajorVersion > 1 || ( leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16 ) )
           {
               // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
               // on corruption in later versions.
               opts.paranoid_checks = true;
           }

           _read_options.verify_checksums = true;
           _iter_options.verify_checksums = true;
           _iter_options.fill_cache = false;
           _sync_options.sync = true;

           // Given path must exist to succeed toNativeAnsiPath
           fc::create_directories( dir );
           std::string ldbPath = dir.to_native_ansi_path();

           ldb::DB* ndb = nullptr;
           const auto ntrxstat = ldb::DB::Open( opts, ldbPath.c_str(), &ndb );
           if( !ntrxstat.ok() )
           {
               elog( "Failure opening database: ${db}\nStatus: ${msg}", ("db",dir)("msg",ntrxstat.ToString()) );
               FC_THROW_EXCEPTION( level_map_open_failure, "Failure opening database: ${db}\nStatus: ${msg}",
                                   ("db",dir)("msg",ntrxstat.ToString()) );
           }
           _db.reset( ndb );

           try_upgrade_db( dir, ndb, fc::get_typename<Value>::name(), sizeof( Value ) );
        } FC_CAPTURE_AND_RETHROW( (dir)(create)(cache_size) ) }

        bool is_open()const
        {
          return !!_db;
        }

        void close()
        {
          _db.reset();
          _cache.reset();
        }

        fc::optional<Value> fetch_optional( const Key& k )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           auto itr = find( k );
           if( itr.valid() ) return itr.value();
           return fc::optional<Value>();
        } FC_RETHROW_EXCEPTIONS( warn, "" ) }

        Value fetch( const Key& k )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );
           std::string value;
           auto status = _db->Get( _read_options, ks, &value );
           if( status.IsNotFound() )
           {
             FC_THROW_EXCEPTION( fc::key_not_found_exception, "unable to find key ${key}", ("key",k) );
           }
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
           fc::datastream<const char*> ds(value.c_str(), value.size());
           Value tmp;
           fc::raw::unpack(ds, tmp);
           return tmp;
        } FC_RETHROW_EXCEPTIONS( warn, "error fetching key ${key}", ("key",k) ); }

        class iterator
        {
           public:
             iterator(){}
             bool valid()const
             {
                return _it && _it->Valid();
             }

             Key key()const
             {
                 Key tmp_key;
                 fc::datastream<const char*> ds2( _it->key().data(), _it->key().size() );
                 fc::raw::unpack( ds2, tmp_key );
                 return tmp_key;
             }

             Value value()const
             {
               Value tmp_val;
               fc::datastream<const char*> ds( _it->value().data(), _it->value().size() );
               fc::raw::unpack( ds, tmp_val );
               return tmp_val;
             }

             iterator& operator++()    { _it->Next(); return *this; }
             iterator& operator--()    { _it->Prev(); return *this; }

           protected:
             friend class level_map;
             iterator( ldb::Iterator* it )
             :_it(it){}

             std::shared_ptr<ldb::Iterator> _it;
        };

        iterator begin() const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->SeekToFirst();

           if( itr._it->status().IsNotFound() )
           {
             FC_THROW_EXCEPTION( fc::key_not_found_exception, "" );
           }
           if( !itr._it->status().ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", itr._it->status().ToString() ) );
           }

           if( itr.valid() )
           {
              return itr;
           }
           return iterator();
        } FC_RETHROW_EXCEPTIONS( warn, "error seeking to first" ) }

        iterator find( const Key& key )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           ldb::Slice key_slice;

           /** avoid dynamic memory allocation at this step if possible, most
            * keys should be relatively small in size and not require dynamic
            * memory allocation to seralize the key.
            */
           fc::array<char,256+sizeof(Key)>  stack_buffer;

           size_t pack_size = fc::raw::pack_size(key);
           if( pack_size <= stack_buffer.size() )
           {
              fc::datastream<char*> ds( stack_buffer.data, stack_buffer.size() );
              fc::raw::pack( ds ,key );
              key_slice = ldb::Slice( stack_buffer.data, pack_size );
           }
           else
           {
              auto kslice = fc::raw::pack( key );
              key_slice = ldb::Slice( kslice.data(), kslice.size() );
           }

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->Seek( key_slice );
           if( itr.valid() && itr.key() == key )
           {
              return itr;
           }
           return iterator();
        } FC_RETHROW_EXCEPTIONS( warn, "error finding ${key}", ("key",key) ) }

        iterator lower_bound( const Key& key )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( key );
           ldb::Slice key_slice( kslice.data(), kslice.size() );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->Seek( key_slice );
           return itr;
        } FC_RETHROW_EXCEPTIONS( warn, "error finding ${key}", ("key",key) ) }

        iterator last( )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->SeekToLast();
           return itr;
        } FC_RETHROW_EXCEPTIONS( warn, "error finding last" ) }

        bool last( Key& k )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::unique_ptr<ldb::Iterator> it( _db->NewIterator( _iter_options ) );
           FC_ASSERT( it != nullptr );
           it->SeekToLast();
           if( !it->Valid() )
           {
             return false;
           }
           fc::datastream<const char*> ds2( it->key().data(), it->key().size() );
           fc::raw::unpack( ds2, k );
           return true;
        } FC_RETHROW_EXCEPTIONS( warn, "error reading last item from database" ); }

        bool last( Key& k, Value& v )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::unique_ptr<ldb::Iterator> it( _db->NewIterator( _iter_options ) );
           FC_ASSERT( it != nullptr );
           it->SeekToLast();
           if( !it->Valid() )
           {
             return false;
           }
           fc::datastream<const char*> ds( it->value().data(), it->value().size() );
           fc::raw::unpack( ds, v );

           fc::datastream<const char*> ds2( it->key().data(), it->key().size() );
           fc::raw::unpack( ds2, k );
           return true;
        } FC_RETHROW_EXCEPTIONS( warn, "error reading last item from database" ); }

        /** this class allows batched, atomic database writes.
         *  usage:
         *  {
         *    write_batch batch = _db.create_batch();
         *    batch.store(key1, value1);
         *    batch.store(key2, value2);
         *  }
         *  when the batch goes out of scope, the operations are commited to the database
         */
        class write_batch
        {
            private:
                leveldb::WriteBatch   _batch;
                level_map*            _map = nullptr;
                leveldb::WriteOptions _write_options;

                friend class level_map;
                write_batch( level_map* map, bool sync = false ) : _map(map)
                {
                    _write_options.sync = sync;
                }
            public:
                ~write_batch()
                {
                  try
                  {
                    commit();
                  }
                  catch (const fc::canceled_exception&)
                  {
                    throw;
                  }
                  catch (const fc::exception&)
                  {
                    // we're in a destructor, nothing we can do...
                  }
                }

                void commit()
                {
                  try
                  {
                    FC_ASSERT(_map->is_open(), "Database is not open!");

                    ldb::Status status = _map->_db->Write( _write_options, &_batch );
                    if (!status.ok())
                      FC_THROW_EXCEPTION(level_map_failure, "database error while applying batch: ${msg}", ("msg", status.ToString()));
                    _batch.Clear();
                  }
                  FC_RETHROW_EXCEPTIONS(warn, "error applying batch");
                }

                void abort()
                {
                  _batch.Clear();
                }

                void store( const Key& k, const Value& v )
                {
                  std::vector<char> kslice = fc::raw::pack(k);
                  ldb::Slice ks(kslice.data(), kslice.size());

                  auto vec = fc::raw::pack(v);
                  ldb::Slice vs(vec.data(), vec.size());

                  _batch.Put(ks, vs);
                }

                void remove( const Key& k )
                {
                  std::vector<char> kslice = fc::raw::pack(k);
                  ldb::Slice ks(kslice.data(), kslice.size());
                  _batch.Delete(ks);
                }
        };

        write_batch create_batch( bool sync = false )
        {
           FC_ASSERT( is_open(), "Database is not open!" );
           return write_batch( this, sync );
        }

        void store(const Key& k, const Value& v, bool sync = false)
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );

           auto vec = fc::raw::pack(v);
           ldb::Slice vs( vec.data(), vec.size() );

           auto status = _db->Put( sync ? _sync_options : _write_options, ks, vs );
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
        } FC_RETHROW_EXCEPTIONS( warn, "error storing ${key} = ${value}", ("key",k)("value",v) ); }

        void remove( const Key& k, bool sync = false )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );
           auto status = _db->Delete( sync ? _sync_options : _write_options, ks );
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
        } FC_RETHROW_EXCEPTIONS( warn, "error removing ${key}", ("key",k) ); }

        void export_to_json( const fc::path& path )const
        { try {
            FC_ASSERT( is_open(), "Database is not open!" );
            FC_ASSERT( !fc::exists( path ) );

            std::ofstream fs( path.string() );
            fs.write( "[\n", 2 );

            auto iter = begin();
            while( iter.valid() )
            {
                auto str = fc::json::to_pretty_string( std::make_pair( iter.key(), iter.value() ) );
                if( (++iter).valid() ) str += ",";
                str += "\n";
                fs.write( str.c_str(), str.size() );
            }

            fs.write( "]", 1 );
        } FC_CAPTURE_AND_RETHROW( (path) ) }

        // note: this loops through all the items in the database, so it's not exactly fast.  it's intended for debugging, nothing else.
        size_t size() const
        {
          FC_ASSERT( is_open(), "Database is not open!" );

          iterator it = begin();
          size_t count = 0;
          while (it.valid())
          {
            ++count;
            ++it;
          }
          return count;
        }

     private:
        class key_compare : public leveldb::Comparator
        {
          public:
            int Compare( const leveldb::Slice& a, const leveldb::Slice& b )const
            {
               Key ak,bk;
               fc::datastream<const char*> dsa( a.data(), a.size() );
               fc::raw::unpack( dsa, ak );
               fc::datastream<const char*> dsb( b.data(), b.size() );
               fc::raw::unpack( dsb, bk );

               if( ak  < bk ) return -1;
               if( ak == bk ) return 0;
               return 1;
            }

            const char* Name()const { return "key_compare"; }
            void FindShortestSeparator( std::string*, const leveldb::Slice& )const{}
            void FindShortSuccessor( std::string* )const{};
        };

        std::unique_ptr<leveldb::DB>    _db;
        std::unique_ptr<leveldb::Cache> _cache;
        key_compare                     _comparer;

        ldb::ReadOptions                _read_options;
        ldb::ReadOptions                _iter_options;
        ldb::WriteOptions               _write_options;
        ldb::WriteOptions               _sync_options;
  };

} } // bts::db
<commit_msg>Rephrase error message in level_map<commit_after>#pragma once

#include <leveldb/cache.h>
#include <leveldb/comparator.h>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>

#include <bts/db/exception.hpp>
#include <bts/db/upgrade_leveldb.hpp>

#include <fc/filesystem.hpp>
#include <fc/io/json.hpp>
#include <fc/io/raw.hpp>
#include <fc/reflect/reflect.hpp>

#include <fstream>

namespace bts { namespace db {

  namespace ldb = leveldb;

  /**
   *  @brief implements a high-level API on top of Level DB that stores items using fc::raw / reflection
   */
  template<typename Key, typename Value>
  class level_map
  {
     public:
        void open( const fc::path& dir, bool create = true, size_t cache_size = 0 )
        { try {
           FC_ASSERT( !is_open(), "Database is already open!" );

           ldb::Options opts;
           opts.comparator = &_comparer;
           opts.create_if_missing = create;
           opts.max_open_files = 64;
           opts.compression = leveldb::kNoCompression;

           if( cache_size > 0 )
           {
               opts.write_buffer_size = cache_size / 4; // up to two write buffers may be held in memory simultaneously
               _cache.reset( leveldb::NewLRUCache( cache_size / 2 ) );
               opts.block_cache = _cache.get();
           }

           if( ldb::kMajorVersion > 1 || ( leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16 ) )
           {
               // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
               // on corruption in later versions.
               opts.paranoid_checks = true;
           }

           _read_options.verify_checksums = true;
           _iter_options.verify_checksums = true;
           _iter_options.fill_cache = false;
           _sync_options.sync = true;

           // Given path must exist to succeed toNativeAnsiPath
           fc::create_directories( dir );
           std::string ldbPath = dir.to_native_ansi_path();

           ldb::DB* ndb = nullptr;
           const auto ntrxstat = ldb::DB::Open( opts, ldbPath.c_str(), &ndb );
           if( !ntrxstat.ok() )
           {
               elog( "Failure opening database: ${db}\nStatus: ${msg}", ("db",dir)("msg",ntrxstat.ToString()) );
               FC_THROW_EXCEPTION( level_map_open_failure, "Failure opening database: ${db}\nStatus: ${msg}",
                                   ("db",dir)("msg",ntrxstat.ToString()) );
           }
           _db.reset( ndb );

           try_upgrade_db( dir, ndb, fc::get_typename<Value>::name(), sizeof( Value ) );
        } FC_CAPTURE_AND_RETHROW( (dir)(create)(cache_size) ) }

        bool is_open()const
        {
          return !!_db;
        }

        void close()
        {
          _db.reset();
          _cache.reset();
        }

        fc::optional<Value> fetch_optional( const Key& k )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           auto itr = find( k );
           if( itr.valid() ) return itr.value();
           return fc::optional<Value>();
        } FC_RETHROW_EXCEPTIONS( warn, "" ) }

        Value fetch( const Key& k )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );
           std::string value;
           auto status = _db->Get( _read_options, ks, &value );
           if( status.IsNotFound() )
           {
             FC_THROW_EXCEPTION( fc::key_not_found_exception, "unable to find key ${key}", ("key",k) );
           }
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
           fc::datastream<const char*> ds(value.c_str(), value.size());
           Value tmp;
           fc::raw::unpack(ds, tmp);
           return tmp;
        } FC_RETHROW_EXCEPTIONS( warn, "failure fetching key ${key}", ("key",k) ); }

        class iterator
        {
           public:
             iterator(){}
             bool valid()const
             {
                return _it && _it->Valid();
             }

             Key key()const
             {
                 Key tmp_key;
                 fc::datastream<const char*> ds2( _it->key().data(), _it->key().size() );
                 fc::raw::unpack( ds2, tmp_key );
                 return tmp_key;
             }

             Value value()const
             {
               Value tmp_val;
               fc::datastream<const char*> ds( _it->value().data(), _it->value().size() );
               fc::raw::unpack( ds, tmp_val );
               return tmp_val;
             }

             iterator& operator++()    { _it->Next(); return *this; }
             iterator& operator--()    { _it->Prev(); return *this; }

           protected:
             friend class level_map;
             iterator( ldb::Iterator* it )
             :_it(it){}

             std::shared_ptr<ldb::Iterator> _it;
        };

        iterator begin() const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->SeekToFirst();

           if( itr._it->status().IsNotFound() )
           {
             FC_THROW_EXCEPTION( fc::key_not_found_exception, "" );
           }
           if( !itr._it->status().ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", itr._it->status().ToString() ) );
           }

           if( itr.valid() )
           {
              return itr;
           }
           return iterator();
        } FC_RETHROW_EXCEPTIONS( warn, "error seeking to first" ) }

        iterator find( const Key& key )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           ldb::Slice key_slice;

           /** avoid dynamic memory allocation at this step if possible, most
            * keys should be relatively small in size and not require dynamic
            * memory allocation to seralize the key.
            */
           fc::array<char,256+sizeof(Key)>  stack_buffer;

           size_t pack_size = fc::raw::pack_size(key);
           if( pack_size <= stack_buffer.size() )
           {
              fc::datastream<char*> ds( stack_buffer.data, stack_buffer.size() );
              fc::raw::pack( ds ,key );
              key_slice = ldb::Slice( stack_buffer.data, pack_size );
           }
           else
           {
              auto kslice = fc::raw::pack( key );
              key_slice = ldb::Slice( kslice.data(), kslice.size() );
           }

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->Seek( key_slice );
           if( itr.valid() && itr.key() == key )
           {
              return itr;
           }
           return iterator();
        } FC_RETHROW_EXCEPTIONS( warn, "error finding ${key}", ("key",key) ) }

        iterator lower_bound( const Key& key )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( key );
           ldb::Slice key_slice( kslice.data(), kslice.size() );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->Seek( key_slice );
           return itr;
        } FC_RETHROW_EXCEPTIONS( warn, "error finding ${key}", ("key",key) ) }

        iterator last( )const
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           iterator itr( _db->NewIterator( _iter_options ) );
           itr._it->SeekToLast();
           return itr;
        } FC_RETHROW_EXCEPTIONS( warn, "error finding last" ) }

        bool last( Key& k )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::unique_ptr<ldb::Iterator> it( _db->NewIterator( _iter_options ) );
           FC_ASSERT( it != nullptr );
           it->SeekToLast();
           if( !it->Valid() )
           {
             return false;
           }
           fc::datastream<const char*> ds2( it->key().data(), it->key().size() );
           fc::raw::unpack( ds2, k );
           return true;
        } FC_RETHROW_EXCEPTIONS( warn, "error reading last item from database" ); }

        bool last( Key& k, Value& v )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::unique_ptr<ldb::Iterator> it( _db->NewIterator( _iter_options ) );
           FC_ASSERT( it != nullptr );
           it->SeekToLast();
           if( !it->Valid() )
           {
             return false;
           }
           fc::datastream<const char*> ds( it->value().data(), it->value().size() );
           fc::raw::unpack( ds, v );

           fc::datastream<const char*> ds2( it->key().data(), it->key().size() );
           fc::raw::unpack( ds2, k );
           return true;
        } FC_RETHROW_EXCEPTIONS( warn, "error reading last item from database" ); }

        /** this class allows batched, atomic database writes.
         *  usage:
         *  {
         *    write_batch batch = _db.create_batch();
         *    batch.store(key1, value1);
         *    batch.store(key2, value2);
         *  }
         *  when the batch goes out of scope, the operations are commited to the database
         */
        class write_batch
        {
            private:
                leveldb::WriteBatch   _batch;
                level_map*            _map = nullptr;
                leveldb::WriteOptions _write_options;

                friend class level_map;
                write_batch( level_map* map, bool sync = false ) : _map(map)
                {
                    _write_options.sync = sync;
                }
            public:
                ~write_batch()
                {
                  try
                  {
                    commit();
                  }
                  catch (const fc::canceled_exception&)
                  {
                    throw;
                  }
                  catch (const fc::exception&)
                  {
                    // we're in a destructor, nothing we can do...
                  }
                }

                void commit()
                {
                  try
                  {
                    FC_ASSERT(_map->is_open(), "Database is not open!");

                    ldb::Status status = _map->_db->Write( _write_options, &_batch );
                    if (!status.ok())
                      FC_THROW_EXCEPTION(level_map_failure, "database error while applying batch: ${msg}", ("msg", status.ToString()));
                    _batch.Clear();
                  }
                  FC_RETHROW_EXCEPTIONS(warn, "error applying batch");
                }

                void abort()
                {
                  _batch.Clear();
                }

                void store( const Key& k, const Value& v )
                {
                  std::vector<char> kslice = fc::raw::pack(k);
                  ldb::Slice ks(kslice.data(), kslice.size());

                  auto vec = fc::raw::pack(v);
                  ldb::Slice vs(vec.data(), vec.size());

                  _batch.Put(ks, vs);
                }

                void remove( const Key& k )
                {
                  std::vector<char> kslice = fc::raw::pack(k);
                  ldb::Slice ks(kslice.data(), kslice.size());
                  _batch.Delete(ks);
                }
        };

        write_batch create_batch( bool sync = false )
        {
           FC_ASSERT( is_open(), "Database is not open!" );
           return write_batch( this, sync );
        }

        void store(const Key& k, const Value& v, bool sync = false)
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );

           auto vec = fc::raw::pack(v);
           ldb::Slice vs( vec.data(), vec.size() );

           auto status = _db->Put( sync ? _sync_options : _write_options, ks, vs );
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
        } FC_RETHROW_EXCEPTIONS( warn, "error storing ${key} = ${value}", ("key",k)("value",v) ); }

        void remove( const Key& k, bool sync = false )
        { try {
           FC_ASSERT( is_open(), "Database is not open!" );

           std::vector<char> kslice = fc::raw::pack( k );
           ldb::Slice ks( kslice.data(), kslice.size() );
           auto status = _db->Delete( sync ? _sync_options : _write_options, ks );
           if( !status.ok() )
           {
               FC_THROW_EXCEPTION( level_map_failure, "database error: ${msg}", ("msg", status.ToString() ) );
           }
        } FC_RETHROW_EXCEPTIONS( warn, "error removing ${key}", ("key",k) ); }

        void export_to_json( const fc::path& path )const
        { try {
            FC_ASSERT( is_open(), "Database is not open!" );
            FC_ASSERT( !fc::exists( path ) );

            std::ofstream fs( path.string() );
            fs.write( "[\n", 2 );

            auto iter = begin();
            while( iter.valid() )
            {
                auto str = fc::json::to_pretty_string( std::make_pair( iter.key(), iter.value() ) );
                if( (++iter).valid() ) str += ",";
                str += "\n";
                fs.write( str.c_str(), str.size() );
            }

            fs.write( "]", 1 );
        } FC_CAPTURE_AND_RETHROW( (path) ) }

        // note: this loops through all the items in the database, so it's not exactly fast.  it's intended for debugging, nothing else.
        size_t size() const
        {
          FC_ASSERT( is_open(), "Database is not open!" );

          iterator it = begin();
          size_t count = 0;
          while (it.valid())
          {
            ++count;
            ++it;
          }
          return count;
        }

     private:
        class key_compare : public leveldb::Comparator
        {
          public:
            int Compare( const leveldb::Slice& a, const leveldb::Slice& b )const
            {
               Key ak,bk;
               fc::datastream<const char*> dsa( a.data(), a.size() );
               fc::raw::unpack( dsa, ak );
               fc::datastream<const char*> dsb( b.data(), b.size() );
               fc::raw::unpack( dsb, bk );

               if( ak  < bk ) return -1;
               if( ak == bk ) return 0;
               return 1;
            }

            const char* Name()const { return "key_compare"; }
            void FindShortestSeparator( std::string*, const leveldb::Slice& )const{}
            void FindShortSuccessor( std::string* )const{};
        };

        std::unique_ptr<leveldb::DB>    _db;
        std::unique_ptr<leveldb::Cache> _cache;
        key_compare                     _comparer;

        ldb::ReadOptions                _read_options;
        ldb::ReadOptions                _iter_options;
        ldb::WriteOptions               _write_options;
        ldb::WriteOptions               _sync_options;
  };

} } // bts::db
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

#pragma once

#include <sstream>
#include <string>
#include <chrono>
#include <boost/algorithm/string.hpp>
#include <experimental/optional>
#include "production_snitch_base.hh"
#include "exceptions/exceptions.hh"
#include "service/storage_service.hh"
#include "core/file.hh"
#include "log.hh"

namespace locator {

class bad_property_file_error : public std::exception {};

/**
 * cassandra-rackdc.properties file has the following format:
 *
 * dc=<Data Center name>
 * rack=<Rack name>
 * prefer_local=<true|false>
 */
class gossiping_property_file_snitch : public production_snitch_base {
public:
    static constexpr const char* snitch_properties_filename = "cassandra-rackdc.properties";
    // Check the property file for changes every 60s.
    static constexpr timer<>::duration reload_property_file_period() {
        return std::chrono::seconds(60);
    }

    virtual void gossiper_starting() override;
    virtual future<> stop() override;

    gossiping_property_file_snitch(
        const sstring& fname = snitch_properties_filename);

private:
    static logging::logger& logger() {
        static thread_local logging::logger l("gossiping_property_file_snitch");

        return l;
    }

    template <typename... Args>
    void err(const char* fmt, Args&&... args) const {
        logger().error(fmt, std::forward<Args>(args)...);
    }

    template <typename... Args>
    void warn(const char* fmt, Args&&... args) const {
        logger().warn(fmt, std::forward<Args>(args)...);
    }

    void throw_double_declaration(const sstring& key) const {
        err("double \"{}\" declaration in {}", key, _fname);
        throw bad_property_file_error();
    }

    void throw_bad_format(const sstring& line) const {
        err("Bad format in properties file {}: {}", _fname, line);
        throw bad_property_file_error();
    }

    void throw_incomplete_file() const {
        err("Property file {} is incomplete. Both \"dc\" and \"rack\" "
            "labels have to be defined.", _fname);
        throw bad_property_file_error();
    }

    /**
     * Parse the property file and indicate the StorageService and a Gossiper if
     * there was a configuration change.
     *
     * @return a ready-future when we are done
     */
    future<> reload_configuration();

    /**
     * Check if the property file has been modified since the last time we
     * parsed it.
     *
     * @return TRUE if property file has been modified
     */
    future<bool> property_file_was_modified();

    /**
     * Read the propery file if it has changed since the last time we read it.
     */
    future<> read_property_file();

    /**
     * TODO: this function is expected to trigger a Gossiper to reconnect
     * according to the new "prefer_local" value, namely use either an internal
     * or extenal IP address.
     *
     * This is currently relevant to EC2/GCE(?) only.
     */
    void reload_gossiper_state();

    /**
     * Indicate that the snitch has stopped its I/O.
     */
    void set_stopped();

private:
    sstring _fname;
    timer<> _file_reader;
    lw_shared_ptr<file> _sf;
    std::experimental::optional<timespec> _last_file_mod;
    size_t _fsize;
    std::string _srting_buf;
    std::istringstream _istrm;
    bool _gossip_started = false;
    bool _prefer_local = false;
    bool _file_reader_runs = false;
};
} // namespace locator
<commit_msg>gossiping_property_file_snitch: use a logger from i_endpoint_snitch<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

#pragma once

#include <sstream>
#include <string>
#include <chrono>
#include <boost/algorithm/string.hpp>
#include <experimental/optional>
#include "production_snitch_base.hh"
#include "exceptions/exceptions.hh"
#include "service/storage_service.hh"
#include "core/file.hh"
#include "log.hh"

namespace locator {

class bad_property_file_error : public std::exception {};

/**
 * cassandra-rackdc.properties file has the following format:
 *
 * dc=<Data Center name>
 * rack=<Rack name>
 * prefer_local=<true|false>
 */
class gossiping_property_file_snitch : public production_snitch_base {
public:
    static constexpr const char* snitch_properties_filename = "cassandra-rackdc.properties";
    // Check the property file for changes every 60s.
    static constexpr timer<>::duration reload_property_file_period() {
        return std::chrono::seconds(60);
    }

    virtual void gossiper_starting() override;
    virtual future<> stop() override;

    gossiping_property_file_snitch(
        const sstring& fname = snitch_properties_filename);

private:
    static logging::logger& logger() {
        return i_endpoint_snitch::snitch_logger;
    }

    template <typename... Args>
    void err(const char* fmt, Args&&... args) const {
        logger().error(fmt, std::forward<Args>(args)...);
    }

    template <typename... Args>
    void warn(const char* fmt, Args&&... args) const {
        logger().warn(fmt, std::forward<Args>(args)...);
    }

    void throw_double_declaration(const sstring& key) const {
        err("double \"{}\" declaration in {}", key, _fname);
        throw bad_property_file_error();
    }

    void throw_bad_format(const sstring& line) const {
        err("Bad format in properties file {}: {}", _fname, line);
        throw bad_property_file_error();
    }

    void throw_incomplete_file() const {
        err("Property file {} is incomplete. Both \"dc\" and \"rack\" "
            "labels have to be defined.", _fname);
        throw bad_property_file_error();
    }

    /**
     * Parse the property file and indicate the StorageService and a Gossiper if
     * there was a configuration change.
     *
     * @return a ready-future when we are done
     */
    future<> reload_configuration();

    /**
     * Check if the property file has been modified since the last time we
     * parsed it.
     *
     * @return TRUE if property file has been modified
     */
    future<bool> property_file_was_modified();

    /**
     * Read the propery file if it has changed since the last time we read it.
     */
    future<> read_property_file();

    /**
     * TODO: this function is expected to trigger a Gossiper to reconnect
     * according to the new "prefer_local" value, namely use either an internal
     * or extenal IP address.
     *
     * This is currently relevant to EC2/GCE(?) only.
     */
    void reload_gossiper_state();

    /**
     * Indicate that the snitch has stopped its I/O.
     */
    void set_stopped();

private:
    sstring _fname;
    timer<> _file_reader;
    lw_shared_ptr<file> _sf;
    std::experimental::optional<timespec> _last_file_mod;
    size_t _fsize;
    std::string _srting_buf;
    std::istringstream _istrm;
    bool _gossip_started = false;
    bool _prefer_local = false;
    bool _file_reader_runs = false;
};
} // namespace locator
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 - 2022, Intel Corporation
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef LEVELZERO_HPP_INCLUDE
#define LEVELZERO_HPP_INCLUDE

#include <vector>
#include <string>
#include <cstdint>

#include "geopm_topo.h"

namespace geopm
{
    class LevelZero
    {
        public:
            enum geopm_levelzero_domain_e {
                M_DOMAIN_ALL = 0,
                M_DOMAIN_COMPUTE = 1,
                M_DOMAIN_MEMORY = 2,
                M_DOMAIN_SIZE = 3
            };

            LevelZero() = default;
            virtual ~LevelZero() = default;
            /// @brief Number of GPUs on the platform.
            /// @return Number of LevelZero GPUs.
            virtual int num_gpu() const = 0;

            /// @brief Number of GPUs on the platform.
            /// @param [in] domain The GEOPM domain type being targeted
            /// @return Number of LevelZero GPUs or GPU chips.
            virtual int num_gpu(int domain) const = 0;

            /// @brief Get the number of LevelZero frequency domains of a certain type
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return GPU frequency domain count.
            virtual int frequency_domain_count(unsigned int l0_device_idx,
                                               int l0_domain) const = 0;
            /// @brief Get the LevelZero device actual frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device core clock rate in MHz.
            virtual double frequency_status(unsigned int l0_device_idx,
                                            int l0_domain, int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device efficient frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device efficnet clock rate in MHz.
            virtual double frequency_efficient(unsigned int l0_device_idx,
                                               int l0_domain, int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device mininmum frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU minimum frequency in MHz.
            virtual double frequency_min(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device maximum frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU maximum frequency in MHz.
            virtual double frequency_max(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device frequency throttle reasons
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU..
            /// @return Frequency throttle reasons
            virtual uint32_t frequency_throttle_reasons(unsigned int l0_device_idx, int l0_domain,
                                                        int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device mininum and maximum frequency
            ///        control range in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU minimum and maximum frequency range in MHz.
            virtual std::pair<double, double> frequency_range(unsigned int l0_device_idx,
                                                              int l0_domain,
                                                              int l0_domain_idx) const = 0;

            /// @brief Get the number of LevelZero engine domains
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return GPU engine domain count.
            virtual int engine_domain_count(unsigned int l0_device_idx, int l0_domain) const = 0;
            /// @brief Get the LevelZero device active time and timestamp in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU active time and timestamp in microseconds.
            virtual std::pair<uint64_t, uint64_t> active_time_pair(unsigned int l0_device_idx,
                                                                   int l0_domain,
                                                                   int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device active time in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU active time in microseconds.
            virtual uint64_t active_time(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the cachced LevelZero device timestamp for the
            ///        active time value in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device timestamp for the active time value in microseconds.
            virtual uint64_t active_time_timestamp(unsigned int l0_device_idx,
                                                   int l0_domain, int l0_domain_idx) const = 0;

            /// @brief Get the number of LevelZero power domains of a certain type
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The LevelZero device being targeted
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return Accelerator frequency domain count.
            virtual int power_domain_count(int geopm_domain,
                                           unsigned int l0_device_idx,
                                           int l0_domain) const = 0;
            /// @brief Get the LevelZero device default power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU default power limit in milliwatts
            virtual int32_t power_limit_tdp(unsigned int l0_device_idx) const = 0;
            /// @brief Get the LevelZero device minimum power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU minimum power limit in milliwatts
            virtual int32_t power_limit_min(unsigned int l0_device_idx) const = 0;
            /// @brief Get the LevelZero device maximum power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU maximum power limit in milliwatts
            virtual int32_t power_limit_max(unsigned int l0_device_idx) const = 0;

            /// @brief Get the LevelZero device energy and timestamp
            ///        in microjoules and microseconds
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return GPU energy in microjoules and timestamp in microseconds
            virtual std::pair<uint64_t, uint64_t> energy_pair(int geopm_domain, unsigned int l0_device_idx,
                                                              int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device energy in microjoules.
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return GPU energy in microjoules.
            virtual uint64_t energy(int geopm_domain, unsigned int l0_device_idx, int l0_domain,
                                    int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device energy cached timestamp in microseconds
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return Accelerator energy timestamp in microseconds
            virtual uint64_t energy_timestamp(int geopm_domain, unsigned int l0_device_idx, int l0_domain,
                                              int l0_domain_idx) const = 0;

            /// @brief Set min and max frequency for LevelZero device.
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] domain The domain type being targeted
            /// @param [in] range_min Min target frequency in MHz.
            /// @param [in] range_max Max target frequency in MHz.
            virtual void frequency_control(unsigned int l0_device_idx, int l0_domain,
                                           int l0_domain_idx, double range_min,
                                           double range_max) const = 0;
    };

    const LevelZero &levelzero();
}
#endif
<commit_msg>Typo Fixup<commit_after>/*
 * Copyright (c) 2015 - 2022, Intel Corporation
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef LEVELZERO_HPP_INCLUDE
#define LEVELZERO_HPP_INCLUDE

#include <vector>
#include <string>
#include <cstdint>

#include "geopm_topo.h"

namespace geopm
{
    class LevelZero
    {
        public:
            enum geopm_levelzero_domain_e {
                M_DOMAIN_ALL = 0,
                M_DOMAIN_COMPUTE = 1,
                M_DOMAIN_MEMORY = 2,
                M_DOMAIN_SIZE = 3
            };

            LevelZero() = default;
            virtual ~LevelZero() = default;
            /// @brief Number of GPUs on the platform.
            /// @return Number of LevelZero GPUs.
            virtual int num_gpu() const = 0;

            /// @brief Number of GPUs on the platform.
            /// @param [in] domain The GEOPM domain type being targeted
            /// @return Number of LevelZero GPUs or GPU chips.
            virtual int num_gpu(int domain) const = 0;

            /// @brief Get the number of LevelZero frequency domains of a certain type
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return GPU frequency domain count.
            virtual int frequency_domain_count(unsigned int l0_device_idx,
                                               int l0_domain) const = 0;
            /// @brief Get the LevelZero device actual frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device core clock rate in MHz.
            virtual double frequency_status(unsigned int l0_device_idx,
                                            int l0_domain, int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device efficient frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device efficient clock rate in MHz.
            virtual double frequency_efficient(unsigned int l0_device_idx,
                                               int l0_domain, int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device mininmum frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU minimum frequency in MHz.
            virtual double frequency_min(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device maximum frequency in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU maximum frequency in MHz.
            virtual double frequency_max(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device frequency throttle reasons
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU..
            /// @return Frequency throttle reasons
            virtual uint32_t frequency_throttle_reasons(unsigned int l0_device_idx, int l0_domain,
                                                        int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device mininum and maximum frequency
            ///        control range in MHz
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU minimum and maximum frequency range in MHz.
            virtual std::pair<double, double> frequency_range(unsigned int l0_device_idx,
                                                              int l0_domain,
                                                              int l0_domain_idx) const = 0;

            /// @brief Get the number of LevelZero engine domains
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return GPU engine domain count.
            virtual int engine_domain_count(unsigned int l0_device_idx, int l0_domain) const = 0;
            /// @brief Get the LevelZero device active time and timestamp in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU active time and timestamp in microseconds.
            virtual std::pair<uint64_t, uint64_t> active_time_pair(unsigned int l0_device_idx,
                                                                   int l0_domain,
                                                                   int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device active time in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU active time in microseconds.
            virtual uint64_t active_time(unsigned int l0_device_idx, int l0_domain,
                                         int l0_domain_idx) const = 0;
            /// @brief Get the cachced LevelZero device timestamp for the
            ///        active time value in microseconds
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The LevelZero index indicating a particular
            ///        domain of the GPU.
            /// @return GPU device timestamp for the active time value in microseconds.
            virtual uint64_t active_time_timestamp(unsigned int l0_device_idx,
                                                   int l0_domain, int l0_domain_idx) const = 0;

            /// @brief Get the number of LevelZero power domains of a certain type
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The LevelZero device being targeted
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @return Accelerator frequency domain count.
            virtual int power_domain_count(int geopm_domain,
                                           unsigned int l0_device_idx,
                                           int l0_domain) const = 0;
            /// @brief Get the LevelZero device default power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU default power limit in milliwatts
            virtual int32_t power_limit_tdp(unsigned int l0_device_idx) const = 0;
            /// @brief Get the LevelZero device minimum power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU minimum power limit in milliwatts
            virtual int32_t power_limit_min(unsigned int l0_device_idx) const = 0;
            /// @brief Get the LevelZero device maximum power limit in milliwatts
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @return GPU maximum power limit in milliwatts
            virtual int32_t power_limit_max(unsigned int l0_device_idx) const = 0;

            /// @brief Get the LevelZero device energy and timestamp
            ///        in microjoules and microseconds
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return GPU energy in microjoules and timestamp in microseconds
            virtual std::pair<uint64_t, uint64_t> energy_pair(int geopm_domain, unsigned int l0_device_idx,
                                                              int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device energy in microjoules.
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return GPU energy in microjoules.
            virtual uint64_t energy(int geopm_domain, unsigned int l0_device_idx, int l0_domain,
                                    int l0_domain_idx) const = 0;
            /// @brief Get the LevelZero device energy cached timestamp in microseconds
            /// @param [in] geopm_domain The GEOPM domain being targeted
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] l0_domain The LevelZero domain type being targeted
            /// @param [in] l0_domain_idx The index indicating a particular
            ///        Level Zero domain.
            /// @return Accelerator energy timestamp in microseconds
            virtual uint64_t energy_timestamp(int geopm_domain, unsigned int l0_device_idx, int l0_domain,
                                              int l0_domain_idx) const = 0;

            /// @brief Set min and max frequency for LevelZero device.
            /// @param [in] l0_device_idx The index indicating a particular
            ///        Level Zero GPU.
            /// @param [in] domain The domain type being targeted
            /// @param [in] range_min Min target frequency in MHz.
            /// @param [in] range_max Max target frequency in MHz.
            virtual void frequency_control(unsigned int l0_device_idx, int l0_domain,
                                           int l0_domain_idx, double range_min,
                                           double range_max) const = 0;
    };

    const LevelZero &levelzero();
}
#endif
<|endoftext|>


<commit_before>/***
    This file is part of jsonrpc++
    Copyright (C) 2017-2020 Johannes Pohl

    This software may be modified and distributed under the terms
    of the MIT license.  See the LICENSE file for details.
***/

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "jsonrpcpp.hpp"

using namespace std;

TEST_CASE("Main test")
{
    jsonrpcpp::entity_ptr entity =
        jsonrpcpp::Parser::do_parse(R"({"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3})");
    REQUIRE(entity->is_request());
    jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
    REQUIRE(request->method() == "subtract");
    int result = request->params().get<int>("minuend") - request->params().get<int>("subtrahend");
    REQUIRE(result == 19);
    jsonrpcpp::Response response(*request, result);
    REQUIRE(response.id().type() == jsonrpcpp::Id::value_t::integer);
    REQUIRE(response.id().int_id() == 3);
    REQUIRE(response.result() == 19);
    REQUIRE(response.to_json() == nlohmann::json::parse(R"({"jsonrpc": "2.0", "result": 19, "id": 3})"));
}
<commit_msg>added test case for null parameters<commit_after>/***
    This file is part of jsonrpc++
    Copyright (C) 2017-2020 Johannes Pohl

    This software may be modified and distributed under the terms
    of the MIT license.  See the LICENSE file for details.
***/

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "jsonrpcpp.hpp"

using namespace std;

TEST_CASE("Main test")
{
    jsonrpcpp::entity_ptr entity =
        jsonrpcpp::Parser::do_parse(R"({"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3})");
    REQUIRE(entity->is_request());
    jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
    REQUIRE(request->method() == "subtract");
    int result = request->params().get<int>("minuend") - request->params().get<int>("subtrahend");
    REQUIRE(result == 19);
    jsonrpcpp::Response response(*request, result);
    REQUIRE(response.id().type() == jsonrpcpp::Id::value_t::integer);
    REQUIRE(response.id().int_id() == 3);
    REQUIRE(response.result() == 19);
    REQUIRE(response.to_json() == nlohmann::json::parse(R"({"jsonrpc": "2.0", "result": 19, "id": 3})"));
}

TEST_CASE("Null parameter")
{
    jsonrpcpp::entity_ptr entity =
        jsonrpcpp::Parser::do_parse(R"({"jsonrpc": "2.0", "method": "nullrequest", "params": null, "id": 4})");
    REQUIRE(entity->is_request());
    jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
    REQUIRE(request->method() == "nullrequest");
    REQUIRE(request->params().to_json() == nullptr);
    REQUIRE(request->params().is_null() == true);
    int result = 12;
    jsonrpcpp::Response response(*request, result);
    REQUIRE(response.id().type() == jsonrpcpp::Id::value_t::integer);
    REQUIRE(response.id().int_id() == 4);
    REQUIRE(response.result() == 12);
    REQUIRE(response.to_json() == nlohmann::json::parse(R"({"jsonrpc": "2.0", "result": 12, "id": 4})"));
}<|endoftext|>


<commit_before>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <memory>
#include <iostream>

// Armadillo
#include <armadillo>

// HOP
#include <hop>

class TestHillClimbing : public hop::HillClimbing {
  public:
    TestHillClimbing(
        const std::shared_ptr<hop::OptimisationProblem> optimisationProblem)
      : HillClimbing(optimisationProblem),
        velocityIndex_(0){
      velocities_.load("/Users/SRA/Documents/workspace/OnlineOptimisation/test/data/testVel.mat");
    }

    arma::Col<double> getVelocity() {
      return velocities_.col(velocityIndex_++);
    }

  protected:
    unsigned int velocityIndex_;
    arma::mat velocities_;
};

class TestHillClimbingProblem : public hop::OptimisationProblem {
  public:
    TestHillClimbingProblem(
        const unsigned int numberOfDimensions)
      : OptimisationProblem(numberOfDimensions),
        objectiveValueIndex_(0) {
      objectiveValues_.load("/Users/SRA/Documents/workspace/OnlineOptimisation/test/data/testObj.mat");
    }

    std::vector<arma::Col<double>> getParameterHistory() const noexcept {
      return parameterHistory_;
    }

  protected:
    unsigned int objectiveValueIndex_;
    arma::Col<double> objectiveValues_;

    static std::vector<arma::Col<double>> parameterHistory_;

    double getObjectiveValueImplementation(
       const arma::Col<double>& parameter) const override {
       parameterHistory_.push_back(parameter);

      return objectiveValues_.at(objectiveValueIndex_);
    }

    std::string to_string() const noexcept {
      return "TestHillClimbing";
    }
};

decltype(TestHillClimbingProblem::parameterHistory_) TestHillClimbingProblem::parameterHistory_;

TEST_CASE("Hill climbing", "") {
  std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(4));

  TestHillClimbing testHillClimbing(testHillClimbingProblem);
  testHillClimbing.setInitialParameter(arma::zeros<arma::Col<double>>(testHillClimbingProblem->getNumberOfDimensions()));
  testHillClimbing.setMaximalNumberOfIterations(4);

  testHillClimbing.optimise();
  std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();
  arma::Mat<double> expectedParameterHistory;
  expectedParameterHistory.load("/Users/SRA/Documents/workspace/OnlineOptimisation/test/data/testExp.mat");

  for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
    arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
    arma::Col<double> actualParameter = actualParameterHistory.at(n);

    for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
      CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
    }
  }
}

<commit_msg>Test: Update hillClimbing test<commit_after>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <memory>
#include <iostream>

// Boost
#include <boost/filesystem.hpp>

// Armadillo
#include <armadillo>

// HOP
#include <hop>

extern boost::filesystem::path testDirectory;
static std::string dataPath_ = "/data/optimisationAlgorithm/trajectoryBasedAlgrorithm/hillClimbing/";

class TestHillClimbing : public hop::HillClimbing {
  public:
    TestHillClimbing(
        const std::shared_ptr<hop::OptimisationProblem> optimisationProblem)
      : HillClimbing(optimisationProblem),
        velocityIndex_(0){
      velocities_.load(testDirectory.string() + dataPath_ + "velocities.mat");
    }

    arma::Col<double> getVelocity() {
      return velocities_.col(velocityIndex_++);
    }

  protected:
    unsigned int velocityIndex_;
    arma::mat velocities_;
};

class TestHillClimbingProblem : public hop::OptimisationProblem {
  public:
    TestHillClimbingProblem(
        const unsigned int numberOfDimensions)
      : OptimisationProblem(numberOfDimensions),
        ValueIndex_(0) {
      objectiveValues_.load(testDirectory.string() + dataPath_ + "objectiveValues.mat");
      softConstraintsValues_.load(testDirectory.string() + dataPath_ + "softConstraintsValues.mat");
    }

    std::vector<arma::Col<double>> getParameterHistory() const noexcept {
      return parameterHistory_;
    }

  protected:
    unsigned int ValueIndex_;
    arma::Col<double> objectiveValues_;
    arma::Col<double> softConstraintsValues_;

    static std::vector<arma::Col<double>> parameterHistory_;

    double getObjectiveValueImplementation(
       const arma::Col<double>& parameter) const override {
       parameterHistory_.push_back(parameter);

      return objectiveValues_.at(ValueIndex_);
    }

    double getSoftConstraintsValueImplementation(
       const arma::Col<double>& parameter) const override {

      return softConstraintsValues_.at(ValueIndex_);
    }

    std::string to_string() const noexcept {
      return "TestHillClimbing";
    }
};

decltype(TestHillClimbingProblem::parameterHistory_) TestHillClimbingProblem::parameterHistory_;

TEST_CASE("Hill climbing", "") {

   // Values OptimisationProblem
   double dimension = 4;

   // Values OptimisationAlgorithm
   arma::mat velocities;
   velocities.load(testDirectory.string() + dataPath_ + "velocities.mat");

   // Load Expected
   arma::Mat<double> expectedParameterHistory;
   expectedParameterHistory.load(testDirectory.string() + dataPath_ + "expected.mat");

  std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(dimension));

  arma::Col<double> upperBounds;
  if(upperBounds.quiet_load(testDirectory.string() + dataPath_ + "upperBounds.mat")) {
    testHillClimbingProblem->setUpperBounds(upperBounds);
  };
  arma::Col<double> lowerBounds;
  if(upperBounds.quiet_load(testDirectory.string() + dataPath_ + "lowerBounds.mat")) {
    testHillClimbingProblem->setLowerBounds(lowerBounds);
  }

  TestHillClimbing testHillClimbing(testHillClimbingProblem);
  arma::Col<double> initialParameter;
  if(initialParameter.quiet_load(testDirectory.string() + dataPath_ + "initialParameter.mat")){
    testHillClimbing.setInitialParameter(initialParameter);
  };
  arma::Col<double> maximalStepSize;
  if(maximalStepSize.quiet_load(testDirectory.string() + dataPath_ + "maximalStepSize.mat")){
    testHillClimbing.setMaximalStepSize(maximalStepSize);
  };

  testHillClimbing.optimise();

  std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();

  for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
    arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
    arma::Col<double> actualParameter = actualParameterHistory.at(n);

    for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
      CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
    }
  }
}

<|endoftext|>


<commit_before>//===-- RegularExpression.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/RegularExpression.h"
#include "llvm/ADT/StringRef.h"
#include <string.h>

using namespace lldb_private;

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
RegularExpression::RegularExpression() :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re, int flags) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(flags)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

RegularExpression::RegularExpression(const RegularExpression &rhs)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(rhs.GetText(), rhs.GetCompileFlags());
}

const RegularExpression &
RegularExpression::operator= (const RegularExpression &rhs)
{
    if (&rhs != this)
    {
        Compile (rhs.GetText(), rhs.GetCompileFlags());
    }
    return *this;
}
//----------------------------------------------------------------------
// Destructor
//
// Any previously compiled regular expression contained in this
// object will be freed.
//----------------------------------------------------------------------
RegularExpression::~RegularExpression()
{
    Free();
}

//----------------------------------------------------------------------
// Compile a regular expression using the supplied regular
// expression text and flags. The compiled regular expression lives
// in this object so that it can be readily used for regular
// expression matches. Execute() can be called after the regular
// expression is compiled. Any previously compiled regular
// expression contained in this object will be freed.
//
// RETURNS
//  True if the regular expression compiles successfully, false
//  otherwise.
//----------------------------------------------------------------------
bool
RegularExpression::Compile(const char* re)
{
    return Compile (re, m_compile_flags);
}

bool
RegularExpression::Compile(const char* re, int flags)
{
    Free();
    m_compile_flags = flags;

    if (re && re[0])
    {
        m_re = re;
        m_comp_err = ::regcomp (&m_preg, re, flags);
    }
    else
    {
        // No valid regular expression
        m_comp_err = 1;
    }

    return m_comp_err == 0;
}

//----------------------------------------------------------------------
// Execute a regular expression match using the compiled regular
// expression that is already in this object against the match
// string "s". If any parens are used for regular expression
// matches "match_count" should indicate the number of regmatch_t
// values that are present in "match_ptr". The regular expression
// will be executed using the "execute_flags".
//---------------------------------------------------------------------
bool
RegularExpression::Execute(const char* s, Match *match, int execute_flags) const
{
    int err = 1;
    if (s != NULL && m_comp_err == 0)
    {
        if (match)
        {
            err = ::regexec (&m_preg,
                             s,
                             match->GetSize(),
                             match->GetData(),
                             execute_flags);
        }
        else
        {
            err = ::regexec (&m_preg,
                             s,
                             0,
                             NULL,
                             execute_flags);
        }
    }

    if (err != 0)
    {
        // The regular expression didn't compile, so clear the matches
        if (match)
            match->Clear();
        return false;
    }
    return true;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
{
    if (idx < m_matches.size())
    {
        if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
        {
            // Matched the empty string...
            match_str.clear();
            return true;
        }
        else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
        {
            match_str.assign (s + m_matches[idx].rm_so,
                              m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
{
    if (idx < m_matches.size())
    {
        if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
        {
            // Matched the empty string...
            match_str = llvm::StringRef();
            return true;
        }
        else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
        {
            match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
{
    if (idx1 < m_matches.size() && idx2 < m_matches.size())
    {
        if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
        {
            // Matched the empty string...
            match_str = llvm::StringRef();
            return true;
        }
        else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
        {
            match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
            return true;
        }
    }
    return false;
}

//----------------------------------------------------------------------
// Returns true if the regular expression compiled and is ready
// for execution.
//----------------------------------------------------------------------
bool
RegularExpression::IsValid () const
{
    return m_comp_err == 0;
}

//----------------------------------------------------------------------
// Returns the text that was used to compile the current regular
// expression.
//----------------------------------------------------------------------
const char*
RegularExpression::GetText () const
{
    if (m_re.empty())
        return NULL;
    return m_re.c_str();
}

//----------------------------------------------------------------------
// Free any contained compiled regular expressions.
//----------------------------------------------------------------------
void
RegularExpression::Free()
{
    if (m_comp_err == 0)
    {
        m_re.clear();
        regfree(&m_preg);
        // Set a compile error since we no longer have a valid regex
        m_comp_err = 1;
    }
}

size_t
RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
{
    if (m_comp_err == 0)
    {
        if (err_str && err_str_max_len)
            *err_str = '\0';
        return 0;
    }

    return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
}

bool
RegularExpression::operator < (const RegularExpression& rhs) const
{
    return (m_re < rhs.m_re);
}

<commit_msg>Re-use the GetMatchAtIndex() that uses the StringRef to avoid code duplication and properly detect when a capture is invalid and return false.<commit_after>//===-- RegularExpression.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/RegularExpression.h"
#include "llvm/ADT/StringRef.h"
#include <string.h>

using namespace lldb_private;

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
RegularExpression::RegularExpression() :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re, int flags) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(flags)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

//----------------------------------------------------------------------
// Constructor that compiles "re" using "flags" and stores the
// resulting compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(const char* re) :
    m_re(),
    m_comp_err (1),
    m_preg(),
    m_compile_flags(REG_EXTENDED)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(re);
}

RegularExpression::RegularExpression(const RegularExpression &rhs)
{
    memset(&m_preg,0,sizeof(m_preg));
    Compile(rhs.GetText(), rhs.GetCompileFlags());
}

const RegularExpression &
RegularExpression::operator= (const RegularExpression &rhs)
{
    if (&rhs != this)
    {
        Compile (rhs.GetText(), rhs.GetCompileFlags());
    }
    return *this;
}
//----------------------------------------------------------------------
// Destructor
//
// Any previously compiled regular expression contained in this
// object will be freed.
//----------------------------------------------------------------------
RegularExpression::~RegularExpression()
{
    Free();
}

//----------------------------------------------------------------------
// Compile a regular expression using the supplied regular
// expression text and flags. The compiled regular expression lives
// in this object so that it can be readily used for regular
// expression matches. Execute() can be called after the regular
// expression is compiled. Any previously compiled regular
// expression contained in this object will be freed.
//
// RETURNS
//  True if the regular expression compiles successfully, false
//  otherwise.
//----------------------------------------------------------------------
bool
RegularExpression::Compile(const char* re)
{
    return Compile (re, m_compile_flags);
}

bool
RegularExpression::Compile(const char* re, int flags)
{
    Free();
    m_compile_flags = flags;

    if (re && re[0])
    {
        m_re = re;
        m_comp_err = ::regcomp (&m_preg, re, flags);
    }
    else
    {
        // No valid regular expression
        m_comp_err = 1;
    }

    return m_comp_err == 0;
}

//----------------------------------------------------------------------
// Execute a regular expression match using the compiled regular
// expression that is already in this object against the match
// string "s". If any parens are used for regular expression
// matches "match_count" should indicate the number of regmatch_t
// values that are present in "match_ptr". The regular expression
// will be executed using the "execute_flags".
//---------------------------------------------------------------------
bool
RegularExpression::Execute(const char* s, Match *match, int execute_flags) const
{
    int err = 1;
    if (s != NULL && m_comp_err == 0)
    {
        if (match)
        {
            err = ::regexec (&m_preg,
                             s,
                             match->GetSize(),
                             match->GetData(),
                             execute_flags);
        }
        else
        {
            err = ::regexec (&m_preg,
                             s,
                             0,
                             NULL,
                             execute_flags);
        }
    }

    if (err != 0)
    {
        // The regular expression didn't compile, so clear the matches
        if (match)
            match->Clear();
        return false;
    }
    return true;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
{
    llvm::StringRef match_str_ref;
    if (GetMatchAtIndex(s, idx, match_str_ref))
    {
        match_str = std::move(match_str_ref.str());
        return true;
    }
    return false;
}

bool
RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
{
    if (idx < m_matches.size())
    {
        if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
            return false;

        if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
        {
            // Matched the empty string...
            match_str = llvm::StringRef();
            return true;
        }
        else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
        {
            match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
            return true;
        }
    }
    return false;
}

bool
RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
{
    if (idx1 < m_matches.size() && idx2 < m_matches.size())
    {
        if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
        {
            // Matched the empty string...
            match_str = llvm::StringRef();
            return true;
        }
        else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
        {
            match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
            return true;
        }
    }
    return false;
}

//----------------------------------------------------------------------
// Returns true if the regular expression compiled and is ready
// for execution.
//----------------------------------------------------------------------
bool
RegularExpression::IsValid () const
{
    return m_comp_err == 0;
}

//----------------------------------------------------------------------
// Returns the text that was used to compile the current regular
// expression.
//----------------------------------------------------------------------
const char*
RegularExpression::GetText () const
{
    if (m_re.empty())
        return NULL;
    return m_re.c_str();
}

//----------------------------------------------------------------------
// Free any contained compiled regular expressions.
//----------------------------------------------------------------------
void
RegularExpression::Free()
{
    if (m_comp_err == 0)
    {
        m_re.clear();
        regfree(&m_preg);
        // Set a compile error since we no longer have a valid regex
        m_comp_err = 1;
    }
}

size_t
RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
{
    if (m_comp_err == 0)
    {
        if (err_str && err_str_max_len)
            *err_str = '\0';
        return 0;
    }

    return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
}

bool
RegularExpression::operator < (const RegularExpression& rhs) const
{
    return (m_re < rhs.m_re);
}

<|endoftext|>


<commit_before>#include <iostream>

#include "floaxie/dtoa.h"

using namespace std;
using namespace floaxie;

int main(int, char**)
{
	double pi = 0.1;
	char buffer[128];

	for (int i = 0; i < 128; ++i)
		buffer[i] = 0;

	dtoa(pi, buffer);
	std::cout << "pi: " << pi << ", buffer: " << buffer << std::endl;

	return 0;
}
<commit_msg>Remove unnecessary zeroing out of output buffer<commit_after>#include <iostream>

#include "floaxie/dtoa.h"

using namespace std;
using namespace floaxie;

int main(int, char**)
{
	double pi = 0.1;
	char buffer[128];

	dtoa(pi, buffer);
	std::cout << "pi: " << pi << ", buffer: " << buffer << std::endl;

	return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file speed_optimizer.cc
 **/

#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/speed_limit.h"
#include "modules/planning/tasks/speed_optimizer.h"

namespace apollo {
namespace planning {

using apollo::planning_internal::StGraphBoundaryDebug;
using apollo::planning_internal::STGraphDebug;

SpeedOptimizer::SpeedOptimizer(const std::string& name) : Task(name) {}

apollo::common::Status SpeedOptimizer::Execute(
    Frame* frame, ReferenceLineInfo* reference_line_info) {
  Task::Execute(frame, reference_line_info);

  auto ret = Process(
      reference_line_info->AdcSlBoundary(), reference_line_info->path_data(),
      frame->PlanningStartPoint(), reference_line_info->reference_line(),
      reference_line_info->path_decision(),
      reference_line_info->mutable_speed_data());

  if (!ret.ok() && FLAGS_enable_slowdown_profile_generator) {
    *reference_line_info->mutable_speed_data() =
        GenerateStopProfile(frame->PlanningStartPoint().v());
  }
  RecordDebugInfo(reference_line_info->speed_data());
  return ret;
}

SpeedData SpeedOptimizer::GenerateStopProfile(const double init_speed) const {
  AERROR << "Slowing down the car.";
  SpeedData speed_data;

  double slowdown_decel = FLAGS_slowdown_profile_deceleration;
  if (frame_->PlanningStartPoint().v() > FLAGS_slowdown_speed_threshold) {
    // TODO(all): select the best deceleration for slow down.
    slowdown_decel = FLAGS_slowdown_speed_threshold / 2.0;
  }

  const size_t max_t = 3.0;
  const double unit_t = 0.02;

  double pre_s = 0.0;
  for (double t = 0.0; t < max_t; t += unit_t) {
    const double s =
        std::fmax(pre_s, init_speed * t + 0.5 * slowdown_decel * t * t);
    const double v = std::fmax(0.0, init_speed + slowdown_decel * t);
    speed_data.AppendSpeedPoint(s, t, v, slowdown_decel, 0.0);
    pre_s = s;
  }
  return speed_data;
}

void SpeedOptimizer::RecordDebugInfo(const SpeedData& speed_data) {
  auto debug = frame_->MutableADCTrajectory()->mutable_debug();
  auto ptr_speed_plan = debug->mutable_planning_data()->add_speed_plan();
  ptr_speed_plan->set_name(Name());
  ptr_speed_plan->mutable_speed_point()->CopyFrom(
      {speed_data.speed_vector().begin(), speed_data.speed_vector().end()});
}

void SpeedOptimizer::RecordSTGraphDebug(
    const std::vector<StBoundary>& boundaries, const SpeedLimit& speed_limits,
    const SpeedData& speed_data, STGraphDebug* st_graph_debug) {
  if (!FLAGS_enable_record_debug) {
    ADEBUG << "Skip record debug info";
    return;
  }

  // auto debug = frame_->MutableADCTrajectory()->mutable_debug();
  // auto st_graph_debug = debug->mutable_planning_data()->add_st_graph();
  st_graph_debug->set_name(Name());
  for (const auto boundary : boundaries) {
    auto boundary_debug = st_graph_debug->add_boundary();
    boundary_debug->set_name(boundary.id());
    switch (boundary.boundary_type()) {
      case StBoundary::BoundaryType::FOLLOW:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_FOLLOW);
        break;
      case StBoundary::BoundaryType::OVERTAKE:
        boundary_debug->set_type(
            StGraphBoundaryDebug::ST_BOUNDARY_TYPE_OVERTAKE);
        break;
      case StBoundary::BoundaryType::STOP:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_STOP);
        break;
      case StBoundary::BoundaryType::UNKNOWN:
        boundary_debug->set_type(
            StGraphBoundaryDebug::ST_BOUNDARY_TYPE_UNKNOWN);
        break;
      case StBoundary::BoundaryType::YIELD:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_YIELD);
        break;
    }

    for (const auto point : boundary.points()) {
      auto point_debug = boundary_debug->add_point();
      point_debug->set_t(point.x());
      point_debug->set_s(point.y());
    }
  }

  for (const auto point : speed_limits.speed_limit_points()) {
    common::SpeedPoint speed_point;
    speed_point.set_s(point.first);
    speed_point.set_v(point.second);
    st_graph_debug->add_speed_limit()->CopyFrom(speed_point);
  }

  st_graph_debug->mutable_speed_profile()->CopyFrom(
      {speed_data.speed_vector().begin(), speed_data.speed_vector().end()});
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: fixed slowdown deceleration.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file speed_optimizer.cc
 **/

#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/speed_limit.h"
#include "modules/planning/tasks/speed_optimizer.h"

namespace apollo {
namespace planning {

using apollo::planning_internal::StGraphBoundaryDebug;
using apollo::planning_internal::STGraphDebug;

SpeedOptimizer::SpeedOptimizer(const std::string& name) : Task(name) {}

apollo::common::Status SpeedOptimizer::Execute(
    Frame* frame, ReferenceLineInfo* reference_line_info) {
  Task::Execute(frame, reference_line_info);

  auto ret = Process(
      reference_line_info->AdcSlBoundary(), reference_line_info->path_data(),
      frame->PlanningStartPoint(), reference_line_info->reference_line(),
      reference_line_info->path_decision(),
      reference_line_info->mutable_speed_data());

  if (!ret.ok() && FLAGS_enable_slowdown_profile_generator) {
    *reference_line_info->mutable_speed_data() =
        GenerateStopProfile(frame->PlanningStartPoint().v());
  }
  RecordDebugInfo(reference_line_info->speed_data());
  return ret;
}

SpeedData SpeedOptimizer::GenerateStopProfile(const double init_speed) const {
  AERROR << "Slowing down the car.";
  SpeedData speed_data;

  double slowdown_decel = FLAGS_slowdown_profile_deceleration;
  if (frame_->PlanningStartPoint().v() > FLAGS_slowdown_speed_threshold) {
    // TODO(all): select the best deceleration for slow down.
    slowdown_decel = FLAGS_slowdown_profile_deceleration / 2.0;
  }

  const size_t max_t = 3.0;
  const double unit_t = 0.02;

  double pre_s = 0.0;
  for (double t = 0.0; t < max_t; t += unit_t) {
    const double s =
        std::fmax(pre_s, init_speed * t + 0.5 * slowdown_decel * t * t);
    const double v = std::fmax(0.0, init_speed + slowdown_decel * t);
    speed_data.AppendSpeedPoint(s, t, v, slowdown_decel, 0.0);
    pre_s = s;
  }
  return speed_data;
}

void SpeedOptimizer::RecordDebugInfo(const SpeedData& speed_data) {
  auto debug = frame_->MutableADCTrajectory()->mutable_debug();
  auto ptr_speed_plan = debug->mutable_planning_data()->add_speed_plan();
  ptr_speed_plan->set_name(Name());
  ptr_speed_plan->mutable_speed_point()->CopyFrom(
      {speed_data.speed_vector().begin(), speed_data.speed_vector().end()});
}

void SpeedOptimizer::RecordSTGraphDebug(
    const std::vector<StBoundary>& boundaries, const SpeedLimit& speed_limits,
    const SpeedData& speed_data, STGraphDebug* st_graph_debug) {
  if (!FLAGS_enable_record_debug) {
    ADEBUG << "Skip record debug info";
    return;
  }

  // auto debug = frame_->MutableADCTrajectory()->mutable_debug();
  // auto st_graph_debug = debug->mutable_planning_data()->add_st_graph();
  st_graph_debug->set_name(Name());
  for (const auto boundary : boundaries) {
    auto boundary_debug = st_graph_debug->add_boundary();
    boundary_debug->set_name(boundary.id());
    switch (boundary.boundary_type()) {
      case StBoundary::BoundaryType::FOLLOW:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_FOLLOW);
        break;
      case StBoundary::BoundaryType::OVERTAKE:
        boundary_debug->set_type(
            StGraphBoundaryDebug::ST_BOUNDARY_TYPE_OVERTAKE);
        break;
      case StBoundary::BoundaryType::STOP:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_STOP);
        break;
      case StBoundary::BoundaryType::UNKNOWN:
        boundary_debug->set_type(
            StGraphBoundaryDebug::ST_BOUNDARY_TYPE_UNKNOWN);
        break;
      case StBoundary::BoundaryType::YIELD:
        boundary_debug->set_type(StGraphBoundaryDebug::ST_BOUNDARY_TYPE_YIELD);
        break;
    }

    for (const auto point : boundary.points()) {
      auto point_debug = boundary_debug->add_point();
      point_debug->set_t(point.x());
      point_debug->set_s(point.y());
    }
  }

  for (const auto point : speed_limits.speed_limit_points()) {
    common::SpeedPoint speed_point;
    speed_point.set_s(point.first);
    speed_point.set_v(point.second);
    st_graph_debug->add_speed_limit()->CopyFrom(speed_point);
  }

  st_graph_debug->mutable_speed_profile()->CopyFrom(
      {speed_data.speed_vector().begin(), speed_data.speed_vector().end()});
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>