You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.9 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2022 Jon Evans <jon@craftyjon.com>
  5. * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef KICAD_DATABASE_CACHE_H
  21. #define KICAD_DATABASE_CACHE_H
  22. #include <chrono>
  23. #include <list>
  24. #include <string>
  25. #include <unordered_map>
  26. #include <database/database_connection.h>
  27. class DATABASE_CACHE
  28. {
  29. public:
  30. typedef std::pair<std::string, std::pair<time_t, DATABASE_CONNECTION::ROW>> CACHE_ENTRY;
  31. DATABASE_CACHE( size_t aMaxSize, time_t aMaxAge ) :
  32. m_maxSize( aMaxSize ),
  33. m_maxAge( aMaxAge )
  34. {}
  35. void Put( const std::string& aQuery, const DATABASE_CONNECTION::ROW& aResult )
  36. {
  37. auto it = m_cache.find( aQuery );
  38. time_t time = std::chrono::system_clock::to_time_t( std::chrono::system_clock::now() );
  39. m_cacheMru.push_front( std::make_pair( aQuery,
  40. std::make_pair( time, aResult ) ) );
  41. if( it != m_cache.end() )
  42. {
  43. m_cacheMru.erase( it->second );
  44. m_cache.erase( it );
  45. }
  46. m_cache[aQuery] = m_cacheMru.begin();
  47. if( m_cache.size() > m_maxSize )
  48. {
  49. auto last = m_cacheMru.end();
  50. last--;
  51. m_cache.erase( last->first );
  52. m_cacheMru.pop_back();
  53. }
  54. }
  55. bool Get( const std::string& aQuery, DATABASE_CONNECTION::ROW& aResult )
  56. {
  57. auto it = m_cache.find( aQuery );
  58. if( it == m_cache.end() )
  59. return false;
  60. time_t time = std::chrono::system_clock::to_time_t( std::chrono::system_clock::now() );
  61. if( time - it->second->second.first > m_maxAge )
  62. {
  63. m_cacheMru.erase( it->second );
  64. m_cache.erase( it );
  65. return false;
  66. }
  67. m_cacheMru.splice( m_cacheMru.begin(), m_cacheMru, it->second );
  68. aResult = it->second->second.second;
  69. return true;
  70. }
  71. void SetMaxSize( size_t aMaxSize ) { m_maxSize = aMaxSize; }
  72. void SetMaxAge( time_t aMaxAge ) { m_maxAge = aMaxAge; }
  73. private:
  74. size_t m_maxSize;
  75. time_t m_maxAge;
  76. std::list<CACHE_ENTRY> m_cacheMru;
  77. std::unordered_map<std::string, std::list<CACHE_ENTRY>::iterator> m_cache;
  78. };
  79. #endif //KICAD_DATABASE_CACHE_H