db_connection.cc
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:14k
- /* Copyright (C) 1998, 1999 State University of New York at Stony Brook
- Author: Andrew V. Shuvalov ( andrew@ecsl.cs.sunysb.edu )
- Software license is located in file "COPYING"
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <errno.h>
- #include <iostream>
- #include <fstream>
- #include "session.h"
- #include "movie_item.h"
- #include "db_connection.h"
- #include "play_commands.h"
- #ifdef _gtk_main_win_h_
- #error "Don't mix database and user interface"
- #endif
- #ifdef _gtk_text_win_h_
- #error "Don't mix database and user interface"
- #endif
- void MovieItem::convertTime( const string &repr, struct tm &dest )
- {
- // time in form: 1997-10-21 10:30:22.0
- string s = repr;
- *(char *)( s.data() + 4 ) = ' ';
- *(char *)( s.data() + 7 ) = ' ';
- *(char *)( s.data() + 10 ) = ' ';
- *(char *)( s.data() + 13 ) = ' ';
- *(char *)( s.data() + 16 ) = ' ';
- *(char *)( s.data() + 19 ) = ' ';
- dest.tm_year = strtol( s.data(), NULL, 10 ) - 1900;
- dest.tm_mon = strtol( s.data() + 5, NULL, 10 ) - 1;
- dest.tm_mday = strtol( s.data() + 8, NULL, 10 );
- dest.tm_hour = strtol( s.data() + 11, NULL, 10 );
- dest.tm_min = strtol( s.data() + 14, NULL, 10 );
- dest.tm_sec = strtol( s.data() + 17, NULL, 10 );
- }
- // --------------------------------------------------
- db_iostream::db_iostream() : iostream(0), everything_read( true )
- {
- skip_to_prompt();
- }
- istream& db_iostream::operator >>( string &s )
- {
- if( everything_read ) {
- s = "";
- return *this;
- }
- char buf[1024];
- if( before_mark )
- {
- // load until mark
- while( !eof() )
- {
- getline( buf, sizeof( buf ));
- if( !buf[0] )
- continue;
- if( buf[0] == '#' ) {
- messages.push_back( s );
- continue;
- }
- if( !strcmp( buf, "->" )) {
- before_mark = false;
- break;
- }
- }
- if( everything_read ) {
- s = "";
- return *this;
- }
- }
- while( !eof() )
- {
- getline( buf, sizeof( buf ));
- // check for special messages, which may indicate error
- if( !s.compare( "#!disconnect" ))
- throw DatabaseException( "disconnected" );
- if( buf[0] == '#' ) {
- messages.push_back( s );
- continue;
- }
- if( !strcmp( buf, "<-" )) {
- skip_to_prompt();
- everything_read = true;
- break;
- }
- s = buf;
- s.c_str(); // terminate
- // cout << s << endl;
- return *this;
- }
- s = "";
- s.c_str(); // terminate
- return *this;
- }
- void db_iostream::skip_to_prompt()
- {
- char buf[ 1024 ];
- // nothing to do
- if( everything_read ) {
- return;
- }
- while( !eof() )
- {
- int ch = peek();
- if( ch == -1 )
- break;
- if( ch != '>' )
- {
- getline( buf, sizeof( buf ));
- if( !buf[0] )
- continue;
- // check for special messages, which may indicate error
- if( !strcmp( buf, "#!disconnect" ))
- throw DatabaseException( "disconnected" );
- if( ch == '#' ) {
- string s( buf );
- messages.push_back( s );
- }
- }
- else // input char by char
- {
- for( int i = 0; i < 3; i++ )
- get( buf[i] );
- buf[3] = ' ';
- string s( buf );
- if( !s.length() )
- continue;
- if( !s.compare( ">>>" ))
- {
- // that means that we got the propmpt and the server will
- // really not post anything before the next command
- everything_read = true;
- break;
- }
- // ups! this is not our string... append the end of string
- getline( buf + 3, sizeof( buf ) );
- }
- }
- }
- void db_iostream::skip_to_prompt( vector< string > &msgs )
- {
- skip_to_prompt();
- append_messages( msgs );
- }
-
- void db_iostream::append_messages( vector< string > &msgs )
- {
- if( !messages.empty() )
- msgs.insert( msgs.end(), messages.begin(), messages.end() );
- messages.clear();
- }
- // --------------------------------------------------
- DbConnection::DbConnection() : dbSockStream( 0 )
- {
- }
- DbConnection::~DbConnection()
- {
- if( dbSockStream )
- delete dbSockStream;
- dbSockStream = 0;
- }
- void DbConnection::connect( const string &server, unsigned int port )
- {
- struct sockaddr_in name;
- name.sin_family = AF_INET;
- name.sin_port = htons (port);
- struct hostent *hostinfo = gethostbyname ( server.c_str() );
- if( hostinfo < 0 ) {
- throw NetworkException( "bad host %s", server.c_str() );
- }
- name.sin_addr = *(struct in_addr *) hostinfo->h_addr;
- // create socket
- int dbSocket = socket (PF_INET, SOCK_STREAM, 0);
- if( dbSocket < 0 )
- {
- dbSocket = 0;
- throw NetworkException( "socket: %s", sys_errlist[ errno ] );
- }
- // now connect
- if( 0 > ::connect( dbSocket, (struct sockaddr *) &name, sizeof (name)))
- {
- dbSocket = 0;
- throw NetworkException( "connect to %s: %s", server.c_str(),
- sys_errlist[ errno ] );
- }
- filebuf *fb = new filebuf( dbSocket );
- if( !fb )
- {
- dbSocket = 0;
- throw NetworkException( "filebuf: %s", sys_errlist[ errno ] );
- }
- dbSockStream = new db_iostream( fb );
- if( dbSockStream <= 0 )
- {
- dbSockStream = 0;
- throw NetworkException( "socket stream: %s", sys_errlist[ errno ] );
- }
- }
- bool DbConnection::login_superuser( const string &passwd,
- vector< string > &messages )
- {
- *dbSockStream << _superuser_ << " " << passwd << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- // if password is false, exception raise
- return true;
- }
- const MovieItem &DbConnection::get_movie_by_id( int id )
- {
- if( movies.find( id ) == movies.end() )
- {
- static MovieItem nothing;
- return nothing;
- }
- return movies[ id ];
- }
- void DbConnection::skip_to_prompt( vector< string > &messages )
- {
- dbSockStream->skip_to_prompt( messages );
- }
- // ==============================================================
- void DbConnection::set_debug( vector< string > &messages, int debugL )
- {
- *dbSockStream << _debug_level_ << " " << debugL << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- }
- string DbConnection::get_database_name( vector< string > &messages )
- {
- if( !dbSockStream )
- throw NetworkException( "get database name: not connected" );
- *dbSockStream << _database_name_ << endl;
- dbSockStream->wait_input();
- string res;
- *dbSockStream >> res;
- dbSockStream->skip_to_prompt( messages );
- if( !res.length() )
- throw SyntaxException( "get database name: empty" );
- return res;
- }
- void DbConnection::load_new_database
- ( vector< string > &messages, const string &dbname )
- {
- *dbSockStream << _database_name_ << " " << dbname << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- // fill map again
- movies.clear();
- *dbSockStream << _list_movies_ << endl;
- dbSockStream->wait_input();
-
- while( true )
- {
- string name;
- *dbSockStream >> name;
- if( !name.length() )
- break;
- string idstr;
- *dbSockStream >> idstr;
- if( !idstr.length() )
- throw SyntaxException( "list movies: wrong reply" );
- int id = atoi( idstr.c_str() );
- string comments_lines_str;
- *dbSockStream >> comments_lines_str;
- if( !comments_lines_str.length() )
- throw SyntaxException( "list movies: wrong reply" );
- int comments_lines = atoi( comments_lines_str.c_str() );
- string comments;
- for( ; comments_lines > 0; comments_lines -- )
- {
- string tmps;
- *dbSockStream >> tmps;
- if( !tmps.length() )
- throw SyntaxException( "list movies: wrong reply" );
- comments += "n" + tmps;
- }
- struct tm start;
- string s;
- *dbSockStream >> s;
- if( !s.length() )
- throw SyntaxException( "list movies: wrong reply" );
- MovieItem::convertTime( s, start );
- struct tm stop;
- *dbSockStream >> s;
- if( !s.length() )
- throw SyntaxException( "list movies: wrong reply" );
- MovieItem::convertTime( s, stop );
- movies[ id ] = MovieItem( name, comments, start, stop );
- }
- dbSockStream->skip_to_prompt( messages );
- dbSockStream->append_messages( messages );
- char buf[200];
- sprintf( buf, "%d movies in database", movies.size() );
- messages.push_back( string( buf ) );
- }
- void DbConnection::load_movie_text( vector< string > &messages,
- int id, TextOfMovieT *tom )
- {
- *dbSockStream << _list_captions_ << " " << id << endl;
- dbSockStream->wait_input();
- tom->clear();
- while( true )
- {
- string t;
- *dbSockStream >> t;
- if( !t.length() )
- break;
-
- struct tm start;
- string s;
- *dbSockStream >> s;
- if( !s.length() )
- throw SyntaxException( "list captions: wrong reply" );
- MovieItem::convertTime( s, start );
- tom->push_back( StringOfText() );
- StringOfText &sot = tom->back();
- sot.set( t, start );
- }
- dbSockStream->skip_to_prompt( messages );
- dbSockStream->append_messages( messages );
- if( !tom->size() )
- messages.push_back( "No text in movie" );
- }
- void DbConnection::getMovieFileListByTime( int id, const struct tm &t,
- MovieFilesT &movieFiles,
- const Session &session,
- vector< string > &messages )
- {
- if( movies.find( id ) == movies.end() )
- return;
- // that means that this movie item may be just created by this line
- // and so its files count will be zero
- MovieItem &mi = movies[ id ];
- if( !mi.getMovieFilesCnt() ) // try to load them...
- loadMovieFileList( id, mi, session, messages );
- mi.findFileListByTime( t, movieFiles );
- }
- void DbConnection::loadMovieFileList( int id, MovieItem &mi,
- const Session &session,
- vector< string > &messages )
- {
- *dbSockStream << _list_mov_files_ << " " << id << endl;
- dbSockStream->wait_input();
- mi.clearMovieFileList();
- while( true )
- {
- string fname;
- *dbSockStream >> fname;
- if( !fname.length() )
- break;
- string s_pushserv_id;
- *dbSockStream >> s_pushserv_id;
- if( !s_pushserv_id.length() )
- break;
- int pushserv_id = atoi( s_pushserv_id.c_str() );
- string ipaddr;
- *dbSockStream >> ipaddr;
- if( !ipaddr.length() )
- break;
- string s_control_port;
- *dbSockStream >> s_control_port;
- if( !s_control_port.length() )
- break;
- int control_port = atoi( s_control_port.c_str() );
- struct tm start;
- string s;
- *dbSockStream >> s;
- if( !s.length() )
- throw SyntaxException( "list captions: wrong reply" );
- MovieItem::convertTime( s, start );
- struct tm stop;
- *dbSockStream >> s;
- if( !s.length() )
- throw SyntaxException( "list captions: wrong reply" );
- MovieItem::convertTime( s, stop );
- mi.addMovieFile( fname, pushserv_id, ipaddr, control_port, start, stop );
- }
- dbSockStream->skip_to_prompt( messages );
- // now select the best push server and filter the result
- // ( we don't need to keep all servers who can play this movie )
- vector< string > best_ips;
- // we have it two now. I think that's enough
- best_ips.push_back( session.best1PushServIP.str() );
- best_ips.push_back( session.best2PushServIP.str() );
- mi.filterBestPushServ( best_ips );
- }
- void DbConnection::loadServerProperties( vector< string > &messages,
- ServerConfigItemVec &props )
- {
- *dbSockStream << _list_properties_ << endl;
- dbSockStream->wait_input();
-
- string numstr;
- *dbSockStream >> numstr;
- if( ! numstr.length() )
- return;
- int num = atoi( numstr.c_str() );
- for( ; num > 0; num-- )
- {
- string k, v, h;
- *dbSockStream >> k;
- if( !k.length() )
- break;
- *dbSockStream >> v;
- if( !v.length() )
- break;
- *dbSockStream >> h;
- if( !h.length() )
- break;
- ServerConfigItem ci( k, v, h );
- props.push_back( ci );
- }
- dbSockStream->skip_to_prompt( messages );
- }
- void DbConnection::saveServerProperties( vector< string > &messages,
- ServerConfigItemVec &props )
- {
- for( int i = 0; i < props.size(); i++ )
- {
- ServerConfigItem &ci = props[i];
-
- *dbSockStream << _set_property_ << endl;
- *dbSockStream << ci.key << "n" << ci.value << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- }
- *dbSockStream << _save_properties_ << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- }
- void DbConnection::fill_channellist( vector< string > &messages,
- channel_infos_mapT &channel_infos_map )
- {
- *dbSockStream << _list_channels_ << endl;
- dbSockStream->wait_input();
- // receive number of channels
- string numstr;
- *dbSockStream >> numstr;
- if( !numstr.length() )
- throw SyntaxException( "fill channellist: wrong reply" );
- int num = atoi( numstr.c_str() );
- for( int i = 0; i < num; i++ )
- {
- string idstr;
- *dbSockStream >> idstr;
- if( !idstr.length() )
- throw SyntaxException( "fill channellist: wrong reply" );
- int Id = atoi( idstr.c_str() );
- string portstr;
- *dbSockStream >> portstr;
- int port = atoi( portstr.c_str() );
- string descr;
- *dbSockStream >> descr;
-
- string activestr;
- *dbSockStream >> activestr;
- bool active = false;
- if( !activestr.compare( "active" ) || !activestr.compare( "true" ))
- active = true;
- // add this to the list
- channel_info::add_new_channel_info( channel_infos_map, Id, port,
- active, descr );
- }
- dbSockStream->skip_to_prompt( messages );
- }
- void DbConnection::start_recording( int channel_id,
- vector< string > &messages )
- {
- char buf[10];
- snprintf( buf, sizeof( buf ), "%d", channel_id );
- *dbSockStream << _start_recording_ << "n" << buf << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- }
- void DbConnection::stop_recording( int channel_id,
- vector< string > &messages )
- {
- char buf[10];
- snprintf( buf, sizeof( buf ), "%d", channel_id );
- *dbSockStream << _stop_recording_ << "n" << buf << endl;
- dbSockStream->wait_input();
- dbSockStream->skip_to_prompt( messages );
- }
- // ======================
- NetworkException::NetworkException( const char *format, ... )
- : BasicException()
- {
- va_list ap;
- va_start( ap, format );
- init( format, ap );
- va_end( ap );
- }
- SyntaxException::SyntaxException( const char *format, ... )
- {
- va_list ap;
- va_start( ap, format );
- init( format, ap );
- va_end( ap );
- }
- DatabaseException::DatabaseException( const char *format, ... )
- {
- va_list ap;
- va_start( ap, format );
- init( format, ap );
- va_end( ap );
- }