00001
00002
00003
00004
00005
00006
00007 #include "uniconfdaemonconn.h"
00008 #include "uniconfdaemon.h"
00009 #include "wvtclstring.h"
00010 #include "wvstrutils.h"
00011
00012
00013
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
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
00198
00199
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
00216
00217
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
00271
00272
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 }