Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Examples  

server.C

Go to the documentation of this file.
00001 // $Id: server.C,v 1.1.1.1 2002/03/24 12:37:02 dvermeir Exp $
00002 #include <fstream>
00003 #include <sstream>
00004 #include <stdexcept>
00005 #include <ctype.h>
00006 #include <dvutil/props.h>
00007 #include <dvutil/tostring.h>
00008 #include <dvutil/file.h>
00009 #include <dvutil/logstream.h>
00010 
00011 #include "index.h"
00012 #include "query.h"
00013 #include "server.h"
00014 
00015 using namespace Dv;
00016 
00017 // This functions attempts to read a line of at most max_size chars.
00018 // It should behave like getline(istream&,string&) except that it
00019 // refuses to read more than max_size characters.
00020 istream&
00021 getmaxline(istream& is, string& line, string::size_type max_size) {
00022 if (is) {
00023   char* buf = new char[max_size+2];
00024   is.getline(buf,max_size+1,'\n');
00025   line = buf;
00026   delete buf;
00027   }
00028 return is;
00029 }
00030 
00031 Server::Server(const string& conf_fn) throw (runtime_error):
00032  config_fn_(conf_fn), max_cmd_(2048), log_(0) {
00033 ifstream ifs(config_fn().c_str());
00034 if (!ifs)
00035   throw runtime_error(config_fn() + ": cannot open");
00036 Util::Props     config(ifs);
00037 
00038 port_ = config["portnr"];
00039 index_fn_ = config["index"];
00040 wordlength_ = config["wordlength"];
00041 ignore_fn_ = config["ignore"];
00042 log_fn_ = config["logfile"];
00043 if (config("maxcmd"))
00044   max_cmd_ = config["maxcmd"];
00045 
00046 log_ = new Dv::Util::logstream(log_fn(), index_fn() );
00047 if (!*log_)
00048   throw runtime_error(log_fn() + ": cannot open");
00049 
00050 // Build index structure.
00051 index_ = new Index(wordlength());
00052 
00053 // Get words to be ignored and add to index.
00054 ifstream ignore_is(ignore_fn().c_str());
00055 if (!ignore_is)
00056   throw runtime_error(ignore_fn() + ": cannot open");
00057 index().ignore(ignore_is);
00058 
00059 // Read index structure from file, if it exists and can be read.
00060 ifstream index_is(index_fn().c_str());
00061 if (index_is)
00062   index_is >> index();
00063 }
00064 
00065 Server::~Server() {
00066 delete log_;
00067 delete index_;
00068 }
00069 
00070 bool
00071 Server::ok_to_index(const string& path, ostream& err) const {
00072 try {
00073   Util::File f(path);
00074   f.expand();
00075 
00076   if (!f.exists()) {
00077     err << error() << path << ": does not exist";
00078     return false;
00079     }
00080   if (f.type() != Util::File::REGULAR) {
00081     err << error() << path << ": not a regular file";
00082     return false;
00083     }
00084   ifstream ifs(path.c_str());
00085   if (!ifs) {
00086     err << error() << path << ": cannot open for reading";
00087     return false;
00088     }
00089   for (size_t i=0; (i<100); ++i) {
00090     char c(ifs.get());
00091     if (c==EOF)
00092       break;
00093     if (isprint(c) || isspace(c)) {
00094       }
00095     else {
00096       err << error() << path << ": not a text file";
00097       return false;
00098       }
00099     }
00100   }
00101 catch (...) {
00102   return false;
00103   }
00104 return true;
00105 }
00106 
00107 
00108 bool
00109 Server::serve(iostream& ios) {
00110 string line;
00111 while (getmaxline(ios, line, max_cmd())) {
00112   if (line.size() > max_cmd() ) {
00113     log() << error() << "command too long, max = " << max_cmd() << endl;
00114     return true;
00115     }
00116 
00117   if (line.size() == 0) {
00118     log() << error() << "empty command" << endl;
00119     return true;
00120     }
00121 
00122   log() << "CMD: " << line << endl;
00123   
00124   istringstream iss(line);
00125 
00126   string command;
00127   iss >> command;
00128 
00129   if (command == "stop") {
00130     log() << "STOP" << endl;
00131     ios << ok() << endl;
00132     return false;
00133     }
00134   else if (command == "save") {
00135     log() << "SAVE" << endl;
00136     ofstream index_os(index_fn().c_str());
00137     if (index_os) {
00138       index_os << index();
00139       index_os.close();
00140           log() << ok() << endl;
00141           ios << ok() << endl;
00142           }
00143     else {
00144       log() << "ERROR SAVING" << endl;
00145       ios << error() << "cannot save to \"" << index_fn() << "\"" << endl;
00146       }
00147     }
00148   else if (command == "add") {
00149     string path;
00150     iss >> path;
00151     ostringstream oss;
00152     if (ok_to_index(path, oss)) {
00153       Util::File f(path); // Should succeed.
00154       path = f.expand().str();
00155       // Check whether path is not already indexed.
00156       time_t ti(index().date(path)); // 0 if not found.
00157       time_t tn(f.last_modified());
00158       if (tn>ti) { // File modified since it was last indexed.
00159         ifstream ifs(f.path());
00160         index().insert(f.str(),ifs);
00161         }
00162       log() << ok() << endl;
00163       ios << ok() << endl;
00164       }
00165     else {
00166       log() << oss.str() << endl;
00167       ios << oss.str() << endl;
00168       }
00169     }
00170   else if (command == "query") {
00171     string qs; // Query text.
00172     getline(iss,qs);
00173     log() << "QUERY " << qs << endl;
00174     try {
00175       Query q(index(), qs);
00176       const Index::Files& r(q.exec());
00177       log() << "ANSWER: " << r.size() << " FILES" << endl;
00178       for (Index::Files::const_iterator f=r.begin(); f!=r.end(); ++f) 
00179         ios << **f << endl;
00180       // end with empty line
00181       ios << endl;
00182       }
00183     catch (exception& e) {
00184       log() << error() << e.what() << endl;
00185       }
00186     }
00187   else {
00188     ios << error() << "unknown command: \"" << command << "\""  << endl;
00189     log() << error() << "unknown command: \"" << command << "\""  << endl;
00190     }
00191   }
00192 return true;
00193 }
00194 

textindexer-0.2 [27 March, 2002]