Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

uniclientgen.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * UniClientGen is a UniConfGen for retrieving data from the
00006  * UniConfDaemon.
00007  */
00008 #include "uniclientgen.h"
00009 #include "wvtclstring.h"
00010 #include "wvtcp.h"
00011 #include "wvaddr.h"
00012 #include "wvresolver.h"
00013 #include "wvmoniker.h"
00014 #include "wvsslstream.h"
00015 
00016 #ifndef _WIN32
00017 #include "wvunixsocket.h"
00018 static UniConfGen *unixcreator(WvStringParm s, IObject *, void *)
00019 {
00020     return new UniClientGen(new WvUnixConn(s));
00021 }
00022 static WvMoniker<UniConfGen> unixreg("unix", unixcreator);
00023 #endif
00024 
00025 static UniConfGen *tcpcreator(WvStringParm _s, IObject *, void *)
00026 {
00027     WvString s(_s);
00028     char *cptr = s.edit();
00029     
00030     if (!strchr(cptr, ':')) // no default port
00031         s.append(":%s", DEFAULT_UNICONF_DAEMON_TCP_PORT);
00032     
00033     return new UniClientGen(new WvTCPConn(s), _s);
00034 }
00035 
00036 static UniConfGen *sslcreator(WvStringParm _s, IObject *, void *)
00037 {
00038     WvString s(_s);
00039     char *cptr = s.edit();
00040     
00041     if (!strchr(cptr, ':')) // no default port
00042         s.append(":%s", DEFAULT_UNICONF_DAEMON_SSL_PORT);
00043     
00044     return new UniClientGen(new WvSSLStream(new WvTCPConn(s), NULL, true), _s);
00045 }
00046 
00047 // if 'obj' is a WvStream, build the uniconf connection around that;
00048 // otherwise, create a new WvStream using 's' as the wvstream moniker.
00049 static UniConfGen *wvstreamcreator(WvStringParm s, IObject *obj, void *)
00050 {
00051     IWvStream *stream = NULL;
00052     if (obj)
00053         stream = mutate<IWvStream>(obj);
00054     if (!stream)
00055         stream = wvcreate<IWvStream>(s);
00056     return new UniClientGen(stream);
00057 }
00058 
00059 static WvMoniker<UniConfGen> tcpreg("tcp", tcpcreator);
00060 static WvMoniker<UniConfGen> sslreg("ssl", sslcreator);
00061 static WvMoniker<UniConfGen> wvstreamreg("wvstream", wvstreamcreator);
00062 
00063 
00064 
00065 /***** UniClientGen *****/
00066 
00067 UniClientGen::UniClientGen(IWvStream *stream, WvStringParm dst) :
00068     conn(NULL), log(WvString("UniClientGen to %s",
00069     dst.isnull() ? *stream->src() : WvString(dst))),
00070     cmdinprogress(false), cmdsuccess(false)
00071 {
00072     conn = new UniClientConn(stream, dst);
00073     conn->setcallback(WvStreamCallback(this,
00074         &UniClientGen::conncallback), NULL);
00075 
00076     deltastream.setcallback(WvStreamCallback(this, &UniClientGen::deltacb), 0);
00077     WvIStreamList::globallist.append(&deltastream, false);
00078 }
00079 
00080 
00081 UniClientGen::~UniClientGen()
00082 {
00083     WvIStreamList::globallist.unlink(&deltastream);
00084 
00085     conn->writecmd(UniClientConn::REQ_QUIT, "");
00086     delete conn;
00087 }
00088 
00089 
00090 bool UniClientGen::isok()
00091 {
00092     return (conn && conn->isok());
00093 }
00094 
00095 
00096 bool UniClientGen::refresh()
00097 {
00098     // FIXME: This should make sure everything in the queue has been flushed
00099     return true;
00100 }
00101 
00102 
00103 WvString UniClientGen::get(const UniConfKey &key)
00104 {
00105     WvString value;
00106     conn->writecmd(UniClientConn::REQ_GET, wvtcl_escape(key));
00107 
00108     if (do_select())
00109     {
00110         if (result_key == key)
00111             value = result;
00112         else
00113             seterror("Error: server sent wrong key pair.");
00114     }
00115     return value;
00116 }
00117 
00118 
00119 void UniClientGen::set(const UniConfKey &key, WvStringParm newvalue)
00120 {
00121     //set_queue.append(new WvString(key), true);
00122     hold_delta();
00123 
00124     if (newvalue.isnull())
00125         conn->writecmd(UniClientConn::REQ_REMOVE, wvtcl_escape(key));
00126     else
00127         conn->writecmd(UniClientConn::REQ_SET,
00128             WvString("%s %s", wvtcl_escape(key), wvtcl_escape(newvalue)));
00129 
00130     unhold_delta();
00131 }
00132 
00133 
00134 bool UniClientGen::haschildren(const UniConfKey &key)
00135 {
00136     conn->writecmd(UniClientConn::REQ_HASCHILDREN, wvtcl_escape(key));
00137 
00138     if (do_select())
00139     {
00140         if (result_key == key && result == "TRUE")
00141             return true;
00142     }
00143 
00144     return false;
00145 }
00146 
00147 
00148 UniClientGen::Iter *UniClientGen::iterator(const UniConfKey &key)
00149 {
00150     result_list = new WvStringList();
00151     conn->writecmd(UniClientConn::REQ_SUBTREE, wvtcl_escape(key));
00152 
00153     if (do_select())
00154         return new RemoteKeyIter(result_list);
00155 
00156     delete result_list;
00157     return new UniConfGen::NullIter();
00158 }
00159     
00160 
00161 void UniClientGen::conncallback(WvStream &stream, void *userdata)
00162 {
00163     if (conn->alarm_was_ticking)
00164     {
00165         // command response took too long!
00166         log(WvLog::Error, "Command timeout; connection closed.\n");
00167         cmdinprogress = false;
00168         cmdsuccess = false;
00169         conn->close();
00170         
00171         return;
00172     }
00173 
00174     UniClientConn::Command command = conn->readcmd();
00175 
00176     switch (command)
00177     {
00178         case UniClientConn::NONE:
00179             // do nothing
00180             break;
00181 
00182         case UniClientConn::REPLY_OK:
00183             cmdsuccess = true;
00184             cmdinprogress = false;
00185             break;
00186 
00187         case UniClientConn::REPLY_FAIL:
00188             result_key = WvString::null;
00189             cmdsuccess = false;
00190             cmdinprogress = false;
00191             break;
00192 
00193         case UniClientConn::REPLY_CHILD:
00194             {
00195                 WvString key(wvtcl_getword(conn->payloadbuf, " "));
00196                 WvString value(wvtcl_getword(conn->payloadbuf, " "));
00197 
00198                 if (!key.isnull() && !value.isnull())
00199                 {
00200                     result_key = key;
00201                     result = value;
00202                     cmdsuccess = true;
00203                 }
00204                 cmdinprogress = false;
00205                 break;
00206 
00207             }
00208 
00209         case UniClientConn::REPLY_ONEVAL:
00210             {
00211                 WvString key(wvtcl_getword(conn->payloadbuf, " "));
00212                 WvString value(wvtcl_getword(conn->payloadbuf, " "));
00213 
00214                 if (!key.isnull() && !value.isnull())
00215                 {
00216                     result_key = key;
00217                     result = value;
00218                     cmdsuccess = true;
00219                 }
00220 
00221                 cmdinprogress = false;
00222                 break;
00223             }
00224 
00225         case UniClientConn::PART_VALUE:
00226             {
00227                 WvString key(wvtcl_getword(conn->payloadbuf, " "));
00228                 WvString value(wvtcl_getword(conn->payloadbuf, " "));
00229 
00230                 if (!key.isnull() && !value.isnull())
00231                 {
00232                     if (result_list)
00233                         result_list->append(new WvString(key), true);
00234                 }
00235                 break;
00236             }
00237 
00238         case UniClientConn::EVENT_HELLO:
00239             {
00240                 WvString server(wvtcl_getword(conn->payloadbuf, " "));
00241 
00242                 if (server.isnull() || strncmp(server, "UniConf", 7))
00243                 {
00244                     // wrong type of server!
00245                     log(WvLog::Error, "Connected to a non-UniConf serer!\n");
00246 
00247                     cmdinprogress = false;
00248                     cmdsuccess = false;
00249                     conn->close();
00250                 }                    
00251                 break;
00252             }
00253 
00254         case UniClientConn::EVENT_NOTICE:
00255             {
00256                 WvString key(wvtcl_getword(conn->payloadbuf, " "));
00257                 WvString value(wvtcl_getword(conn->payloadbuf, " "));
00258                 clientdelta(key, value);
00259             }   
00260 
00261         default:
00262             // discard unrecognized commands
00263             break;
00264     }
00265 }
00266 
00267 
00268 bool UniClientGen::do_select()
00269 {
00270     cmdinprogress = true;
00271     cmdsuccess = false;
00272 
00273     conn->alarm(TIMEOUT);
00274     while (conn->isok() && cmdinprogress)
00275     {
00276         if (conn->select(-1))
00277         {
00278             conn->callback();
00279             conn->alarm(TIMEOUT);
00280         }
00281     }
00282     conn->alarm(-1);
00283 
00284     if (!cmdsuccess)
00285         seterror("Error: server timed out on response.");
00286 
00287     return cmdsuccess;
00288 }
00289 
00290 
00291 
00292 /***** UniClientGen::RemoteKeyIter *****/
00293 
00294 void UniClientGen::RemoteKeyIter::rewind()
00295 {
00296     i.rewind();
00297 }
00298 
00299 
00300 bool UniClientGen::RemoteKeyIter::next()
00301 {
00302     return i.next();
00303 }
00304 
00305 
00306 UniConfKey UniClientGen::RemoteKeyIter::key() const
00307 {
00308     return UniConfKey(*i).last();
00309 }
00310 
00311 void UniClientGen::clientdelta(const UniConfKey &key, WvStringParm value)
00312 {
00313     deltas.append(new UniConfPair(key, value), true);
00314     deltastream.alarm(0);
00315 }
00316 
00317 void UniClientGen::deltacb(WvStream &, void *)
00318 {
00319     hold_delta();
00320     UniConfPairList::Iter i(deltas);
00321 
00322     for (i.rewind(); i.next(); )
00323         delta(i->key(), i->value());
00324 
00325     deltas.zap();
00326     unhold_delta();
00327 }

Generated on Sat Feb 21 21:05:20 2004 for WvStreams by doxygen 1.3.5