00001
00002 #include "sq3_log_db.hpp"
00003 #include <iostream>
00004 #include <sstream>
00005 #include <vector>
00006 #include <cstdio>
00007 #include <cstring>
00008 namespace sq3 {
00009
00010 log_db::log_db( std::string const & filename )
00011 : database()
00012 {
00013 this->database::open(filename);
00014 }
00015
00016 log_db::~log_db()
00017 {
00018 }
00019
00020 int log_db::on_open()
00021 {
00022 if( ! this->is_open() )
00023 {
00024 return SQLITE_ERROR;
00025 }
00026 std::string sql( "create table if not exists log(ts,msg TEXT)" );
00027 this->execute( sql );
00028
00029
00030
00031
00032 this->pragma( "temp_store = MEMORY" );
00033 return SQLITE_OK;
00034 }
00035
00036 int log_db::clear()
00037 {
00038 return this->execute( "delete from log" );
00039 }
00040
00041 static char const * LOG_DB_LOG_INSERT_SQL = "insert into log (ts,msg) values(strftime('%Y-%m-%d %H:%M:%f','now'),?)";
00042
00043
00044 bool log_db::log( std::string const & msg )
00045 {
00046 if( ! this->is_open() )
00047 {
00048 return false;
00049 }
00050 if( msg.empty() ) return true;
00051 statement st( *this, LOG_DB_LOG_INSERT_SQL );
00052 st.bind( 1, msg );
00053 int rc = st.execute();
00054 return rc_is_okay( rc );
00055
00056 }
00057
00058 bool log_db::log(const char *format,...)
00059 {
00060 if( ! this->is_open() )
00061 {
00062 return false;
00063 }
00064 const int buffsz = static_cast<int>( std::max( (size_t) 2048, strlen(format) * 2 ) );
00065 std::vector<char> buffer( buffsz, '\0' );
00066 va_list vargs;
00067 va_start ( vargs, format );
00068 using namespace std;
00069
00070
00071 int size = vsnprintf(&buffer[0], buffsz, format, vargs);
00072 va_end( vargs );
00073 if (size > (buffsz-1))
00074 {
00075
00076 size = buffsz-1;
00077 for( int i = buffsz-4; i < buffsz-1; ++i )
00078 {
00079 buffer[i] = '.';
00080 }
00081 }
00082 buffer[size] = '\0';
00083 if( size )
00084 {
00085 statement st( *this, LOG_DB_LOG_INSERT_SQL );
00086 st.bind( 1, &buffer[0], size );
00087 int rc = st.execute();
00088
00089 return SQLITE_DONE == rc;
00090 }
00091 return true;
00092 }
00093
00094 #undef LOG_DB_LOG_INSERT_SQL
00095
00096 void log_db::show_last( int count )
00097 {
00098 if( ! this->is_open() )
00099 {
00100 return;
00101 }
00102 std::ostream & os = std::cout;
00103 os << "sq3::log_db: most recent "
00104 << count << " entries:\n";
00105 if( ! this->is_open() )
00106 {
00107 os << "ERROR: Log database is not opened!";
00108 return;
00109 }
00110 std::ostringstream fmt;
00111 if( 0 )
00112 {
00113 fmt << "select /*DATETIME(ts)*/ts,msg from log "
00114 << "order by ts desc, rowid desc"
00115 <<" limit " << count
00116 ;
00117 }
00118 else
00119 {
00120 fmt << "select /*DATETIME(ts)*/ts,msg from log "
00121 << "order by ts asc, rowid asc"
00122 <<" limit " << count
00123 ;
00124 }
00125 std::string sql(fmt.str());
00126 statement st( *this, sql );
00127 cursor r = st.get_cursor();
00128 std::string buff;
00129 while( SQLITE_ROW == r.step() )
00130 {
00131 std::string tmp;
00132 r.get( 0, tmp );
00133 os << tmp << ": ";
00134 r.get( 1, tmp );
00135 os << tmp << '\n';
00136 }
00137 }
00138
00139 bool log_db::trim( int count )
00140 {
00141 if( this->is_open() )
00142 {
00143 std::ostringstream os;
00144 os << "delete from log where rowid not in (select rowid from log order by ts desc, rowid desc limit "<<count<<")";
00145 std::string sql( os.str() );
00146 if( SQLITE_OK == this->execute( sql.c_str() ) )
00147 {
00148 this->vacuum();
00149 }
00150 return true;
00151 }
00152 return false;
00153 }
00154
00155 }