uniconfdaemonconn.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * Manages a UniConf daemon session.
00006  */
00007 #include "uniconfdaemonconn.h"
00008 #include "uniconfdaemon.h"
00009 #include "wvtclstring.h"
00010 #include "wvstrutils.h"
00011 
00012 
00013 /***** UniConfDaemonConn *****/
00014 
00015 UniConfDaemonConn::UniConfDaemonConn(WvStream *_s, const UniConf &_root)
00016     : UniClientConn(_s), root(_root)
00017 {
00018     uses_continue_select = true;
00019     addcallback();
00020     writecmd(EVENT_HELLO,
00021              spacecat(wvtcl_escape("UniConf Server ready."),
00022                       wvtcl_escape(UNICONF_PROTOCOL_VERSION)));
00023 }
00024 
00025 
00026 UniConfDaemonConn::~UniConfDaemonConn()
00027 {
00028     close();
00029     terminate_continue_select();
00030     delcallback();
00031 }
00032 
00033 
00034 void UniConfDaemonConn::close()
00035 {
00036     UniClientConn::close();
00037 }
00038 
00039 
00040 void UniConfDaemonConn::addcallback()
00041 {
00042     root.add_callback(this, UniConfCallback(this,
00043                     &UniConfDaemonConn::deltacallback), true);
00044 }
00045 
00046 
00047 void UniConfDaemonConn::delcallback()
00048 {
00049     root.del_callback(this, true);
00050 }
00051 
00052 
00053 void UniConfDaemonConn::execute()
00054 {
00055     UniClientConn::execute();
00056 
00057     WvString command_string;
00058     UniClientConn::Command command = readcmd(command_string);
00059     if (command != UniClientConn::NONE)
00060     {
00061         // parse and execute command
00062         WvString arg1(readarg());
00063         WvString arg2(readarg());
00064         switch (command)
00065         {
00066         case UniClientConn::NONE:
00067             break;
00068             
00069         case UniClientConn::INVALID:
00070             do_invalid(command_string);
00071             break;
00072             
00073         case UniClientConn::REQ_NOOP:
00074             do_noop();
00075             break;
00076             
00077         case UniClientConn::REQ_GET:
00078             if (arg1.isnull())
00079                 do_malformed(command);
00080             else
00081                 do_get(arg1);
00082             break;
00083             
00084         case UniClientConn::REQ_SET:
00085             if (arg1.isnull() || arg2.isnull())
00086                 do_malformed(command);
00087             else
00088                 do_set(arg1, arg2);
00089             break;
00090             
00091         case UniClientConn::REQ_REMOVE:
00092             if (arg1.isnull())
00093                 do_malformed(command);
00094             else
00095                 do_remove(arg1);
00096             break;
00097             
00098         case UniClientConn::REQ_SUBTREE:
00099             if (arg1.isnull())
00100                 do_malformed(command);
00101             else
00102                 do_subtree(arg1, arg2.num() == 1);
00103             break;
00104             
00105         case UniClientConn::REQ_HASCHILDREN:
00106             if (arg1.isnull())
00107                 do_malformed(command);
00108             else
00109                 do_haschildren(arg1);
00110             break;
00111             
00112         case UniClientConn::REQ_COMMIT:
00113             do_commit();
00114             break;
00115             
00116         case UniClientConn::REQ_REFRESH:
00117             do_refresh();
00118             break;
00119             
00120         case UniClientConn::REQ_QUIT:
00121             do_quit();
00122             break;
00123             
00124         case UniClientConn::REQ_HELP:
00125             do_help();
00126             break;
00127             
00128         default:
00129             do_invalid(command_string);
00130             break;
00131         }
00132     }
00133 }
00134 
00135 
00136 void UniConfDaemonConn::do_invalid(WvStringParm c)
00137 {
00138     writefail(WvString("unknown command: %s", c));
00139 }
00140 
00141 
00142 void UniConfDaemonConn::do_malformed(UniClientConn::Command c)
00143 {
00144     writefail(WvString("malformed request: %s",
00145                        UniClientConn::cmdinfos[c].name));
00146 }
00147 
00148 
00149 void UniConfDaemonConn::do_noop()
00150 {
00151     writeok();
00152 }
00153 
00154 
00155 void UniConfDaemonConn::do_reply(WvStringParm reply)
00156 {
00157     writefail("unexpected reply");
00158 }
00159 
00160 
00161 void UniConfDaemonConn::do_get(const UniConfKey &key)
00162 {
00163     WvString value(root[key].getme());
00164     if (value.isnull())
00165         writefail();
00166     else
00167         writeonevalue(key, value);
00168 }
00169 
00170 
00171 void UniConfDaemonConn::do_set(const UniConfKey &key, WvStringParm value)
00172 {
00173     root[key].setme(value);
00174 }
00175 
00176 
00177 void UniConfDaemonConn::do_remove(const UniConfKey &key)
00178 {
00179     root[key].remove();
00180 }
00181 
00182 
00183 void UniConfDaemonConn::do_subtree(const UniConfKey &key, bool recursive)
00184 {
00185     static int niceness = 0;
00186     
00187     UniConf cfg(root[key]);
00188     if (cfg.exists())
00189     {
00190         if (recursive)
00191         {
00192             UniConf::RecursiveIter it(cfg);
00193             for (it.rewind(); it.next(); )
00194             {
00195                 writevalue(it->fullkey(cfg), it._value());
00196                 
00197                 // the output might be totally gigantic.  Don't hog the
00198                 // entire daemon while fulfilling it; give up our timeslice
00199                 // after each entry.
00200                 if (!isok()) break;
00201                 if (++niceness > 100)
00202                 {
00203                     niceness = 0;
00204                     continue_select(0);
00205                 }
00206             }
00207         }
00208         else
00209         {
00210             UniConf::Iter it(cfg);
00211             for (it.rewind(); it.next(); )
00212             {
00213                 writevalue(it->fullkey(cfg), it._value());
00214                 
00215                 // the output might be totally gigantic.  Don't hog the
00216                 // entire daemon while fulfilling it; give up our timeslice
00217                 // after each entry.
00218                 if (!isok()) break;
00219                 continue_select(0);
00220             }
00221         }
00222         writeok();
00223     }
00224     else
00225         writefail();
00226 }
00227 
00228 
00229 void UniConfDaemonConn::do_haschildren(const UniConfKey &key)
00230 {
00231     bool haschild = root[key].haschildren();
00232     writecmd(REPLY_CHILD,
00233              spacecat(wvtcl_escape(key), haschild ? "TRUE" : "FALSE"));
00234 }
00235 
00236 
00237 void UniConfDaemonConn::do_commit()
00238 {
00239     root.commit();
00240     writeok();
00241 }
00242 
00243 
00244 void UniConfDaemonConn::do_refresh()
00245 {
00246     if (root.refresh())
00247         writeok();
00248     else
00249         writefail();
00250 }
00251 
00252 
00253 void UniConfDaemonConn::do_quit()
00254 {
00255     writeok();
00256     close();
00257 }
00258 
00259 
00260 void UniConfDaemonConn::do_help()
00261 {
00262     for (int i = 0; i < UniClientConn::NUM_COMMANDS; ++i)
00263         writetext(UniClientConn::cmdinfos[i].description);
00264     writeok();
00265 }
00266 
00267 
00268 void UniConfDaemonConn::deltacallback(const UniConf &cfg, const UniConfKey &key)
00269 {
00270     // for now, we just send notifications for *any* key that changes.
00271     // Eventually we probably want to do something about having each
00272     // connection specify exactly which keys it cares about.
00273     WvString value(cfg[key].getme());
00274     WvString msg;
00275 
00276     UniConfKey fullkey(cfg.fullkey(cfg));
00277     fullkey.append(key);
00278 
00279     if (value.isnull())
00280         msg = wvtcl_escape(fullkey);
00281     else
00282         msg = spacecat(wvtcl_escape(fullkey),
00283                        wvtcl_escape(cfg[key].getme()));
00284 
00285     writecmd(UniClientConn::EVENT_NOTICE, msg);
00286 }

Generated on Thu May 25 21:51:02 2006 for WvStreams by  doxygen 1.4.6