1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <IceUtil/DisableWarnings.h>
6 #include <IceUtil/FileUtil.h>
7 #include <Ice/Ice.h>
8 #include <IceGrid/ServerI.h>
9 #include <IceGrid/TraceLevels.h>
10 #include <IceGrid/Activator.h>
11 #include <IceGrid/NodeI.h>
12 #include <IceGrid/Util.h>
13 #include <IceGrid/ServerAdapterI.h>
14 #include <IceGrid/DescriptorHelper.h>
15 
16 #include <IcePatch2Lib/Util.h>
17 #include <IceUtil/FileUtil.h>
18 
19 #include <sys/types.h>
20 #include <fstream>
21 
22 #ifdef _WIN32
23 #  include <direct.h>
24 #  include <signal.h>
25 #else
26 #  include <sys/wait.h>
27 #  include <pwd.h> // for getpwnam
28 #  include <signal.h>
29 #  include <unistd.h>
30 #  include <dirent.h>
31 #endif
32 
33 using namespace std;
34 using namespace IceGrid;
35 
36 namespace IceGrid
37 {
38 
39 #ifndef _WIN32
40 void
chownRecursive(const string & path,uid_t uid,gid_t gid)41 chownRecursive(const string& path, uid_t uid, gid_t gid)
42 {
43     vector<vector<Ice::Byte> > namelist;
44     DIR* d;
45     if((d = opendir(path.c_str())) == 0)
46     {
47         throw runtime_error("cannot read directory `" + path + "':\n" + IceUtilInternal::lastErrorToString());
48     }
49 
50     struct dirent* entry;
51     while((entry = readdir(d)) != 0)
52     {
53         size_t index = namelist.size();
54         namelist.resize(index + 1);
55 
56         size_t entrysize = sizeof(struct dirent) - sizeof(entry->d_name) + strlen(entry->d_name) + 1;
57         namelist[index].resize(entrysize);
58 
59         memcpy(&namelist[index][0], entry, entrysize);
60     }
61 
62     if(closedir(d))
63     {
64         throw runtime_error("cannot read directory `" + path + "':\n" + IceUtilInternal::lastErrorToString());
65     }
66 
67     for(size_t i = 0; i < namelist.size(); ++i)
68     {
69         string name = reinterpret_cast<struct dirent*>(&namelist[i][0])->d_name;
70         assert(!name.empty());
71 
72         if(name == ".")
73         {
74             if(chown(path.c_str(), uid, gid) != 0)
75             {
76                 throw runtime_error("can't change permissions on `" + name + "':\n" + IceUtilInternal::lastErrorToString());
77             }
78         }
79         else if(name != "..")
80         {
81             name = path + "/" + name;
82 
83             IceUtilInternal::structstat buf;
84             if(IceUtilInternal::stat(name, &buf) == -1)
85             {
86                 throw runtime_error("cannot stat `" + name + "':\n" + IceUtilInternal::lastErrorToString());
87             }
88 
89             if(S_ISDIR(buf.st_mode))
90             {
91                 chownRecursive(name, uid, gid);
92             }
93             else
94             {
95                 if(chown(name.c_str(), uid, gid) != 0)
96                 {
97                     throw runtime_error("can't change permissions on `" + name + "':\n" + IceUtilInternal::lastErrorToString());
98                 }
99             }
100         }
101     }
102 }
103 #endif
104 
105 static bool
descriptorUpdated(const InternalServerDescriptorPtr & lhs,const InternalServerDescriptorPtr & rhs,bool noProps=false)106 descriptorUpdated(const InternalServerDescriptorPtr& lhs, const InternalServerDescriptorPtr& rhs, bool noProps = false)
107 {
108     if(lhs->uuid == rhs->uuid && lhs->revision == rhs->revision)
109     {
110         return false;
111     }
112 
113     if(lhs->id != rhs->id ||
114        lhs->application != rhs->application ||
115        lhs->uuid != rhs->uuid ||
116        lhs->sessionId != rhs->sessionId ||
117        lhs->exe != rhs->exe ||
118        lhs->pwd != rhs->pwd ||
119        lhs->user != rhs->user ||
120        lhs->activation != rhs->activation ||
121        lhs->activationTimeout != rhs->activationTimeout ||
122        lhs->deactivationTimeout != rhs->deactivationTimeout ||
123        lhs->applicationDistrib != rhs->applicationDistrib ||
124        lhs->processRegistered != rhs->processRegistered ||
125        lhs->options != rhs->options ||
126        lhs->envs != rhs->envs ||
127        lhs->logs != rhs->logs)
128     {
129         return true;
130     }
131 
132     if((!lhs->distrib && rhs->distrib) || (lhs->distrib && !rhs->distrib))
133     {
134         return true;
135     }
136     else if(lhs->distrib && rhs->distrib)
137     {
138         if(lhs->distrib->icepatch != rhs->distrib->icepatch ||
139            lhs->distrib->directories != rhs->distrib->directories)
140         {
141             return true;
142         }
143     }
144 
145     if(lhs->adapters.size() != rhs->adapters.size())
146     {
147         return true;
148     }
149     else
150     {
151         InternalAdapterDescriptorSeq::const_iterator q = rhs->adapters.begin();
152         for(InternalAdapterDescriptorSeq::const_iterator p = lhs->adapters.begin(); p != lhs->adapters.end(); ++p, ++q)
153         {
154             if((*p)->id != (*q)->id || (*p)->serverLifetime != (*q)->serverLifetime)
155             {
156                 return true;
157             }
158         }
159     }
160 
161     if(lhs->dbEnvs.size() != rhs->dbEnvs.size())
162     {
163         return true;
164     }
165     else
166     {
167         InternalDbEnvDescriptorSeq::const_iterator q = rhs->dbEnvs.begin();
168         for(InternalDbEnvDescriptorSeq::const_iterator p = lhs->dbEnvs.begin(); p != lhs->dbEnvs.end(); ++p, ++q)
169         {
170             if((*p)->name != (*q)->name || (*p)->properties != (*q)->properties)
171             {
172                 return true;
173             }
174         }
175     }
176 
177     if(!noProps && lhs->properties != rhs->properties)
178     {
179         return true;
180     }
181 
182     return false;
183 }
184 
185 Ice::PropertyDict
toPropertyDict(const PropertyDescriptorSeq & seq)186 toPropertyDict(const PropertyDescriptorSeq& seq)
187 {
188     Ice::PropertyDict props;
189     for(PropertyDescriptorSeq::const_iterator q = seq.begin(); q != seq.end(); ++q)
190     {
191         if(q->value.empty() && q->name.find('#') == 0)
192         {
193             continue; // Ignore comments.
194         }
195 
196         if(q->value.empty())
197         {
198             props.erase(q->name);
199         }
200         else
201         {
202             props[q->name] = q->value;
203         }
204     }
205     return props;
206 }
207 
208 class CommandTimeoutTimerTask : public IceUtil::TimerTask
209 {
210 public:
211 
CommandTimeoutTimerTask(const TimedServerCommandPtr & command)212     CommandTimeoutTimerTask(const TimedServerCommandPtr& command) : _command(command)
213     {
214     }
215 
runTimerTask()216     virtual void runTimerTask()
217     {
218         _command->timeout();
219     }
220 
221 private:
222 
223     const TimedServerCommandPtr _command;
224 };
225 
226 class DelayedStart : public IceUtil::TimerTask
227 {
228 public:
229 
DelayedStart(const ServerIPtr & server,const TraceLevelsPtr & traceLevels)230     DelayedStart(const ServerIPtr& server, const TraceLevelsPtr& traceLevels) :
231         _server(server),
232         _traceLevels(traceLevels)
233     {
234     }
235 
runTimerTask()236     virtual void runTimerTask()
237     {
238         try
239         {
240             _server->start(ServerI::Always);
241         }
242         catch(const ServerStartException& ex)
243         {
244             Ice::Error out(_traceLevels->logger);
245             out << "couldn't reactivate server `" << _server->getId()
246                 << "' with `always' activation mode after failure:\n"
247                 << ex.reason;
248         }
249         catch(const Ice::ObjectNotExistException&)
250         {
251         }
252     }
253 
254 private:
255 
256     const ServerIPtr _server;
257     const TraceLevelsPtr _traceLevels;
258 };
259 
260 class ResetPropertiesCB : public IceUtil::Shared
261 {
262 public:
263 
ResetPropertiesCB(const ServerIPtr & server,const Ice::ObjectPrx admin,const InternalServerDescriptorPtr & desc,const InternalServerDescriptorPtr & old,const TraceLevelsPtr & traceLevels)264     ResetPropertiesCB(const ServerIPtr& server,
265                       const Ice::ObjectPrx admin,
266                       const InternalServerDescriptorPtr& desc,
267                       const InternalServerDescriptorPtr& old,
268                       const TraceLevelsPtr& traceLevels) :
269         _server(server),
270         _admin(admin),
271         _desc(desc),
272         _traceLevels(traceLevels),
273         _properties(server->getProperties(desc)),
274         _oldProperties(server->getProperties(old)),
275         _p(_properties.begin())
276     {
277     }
278 
279     void
execute()280     execute()
281     {
282         assert(_p != _properties.end());
283         next();
284     }
285 
286 private:
287 
288     void
next()289     next()
290     {
291         while(_p != _properties.end() && _p->second == _oldProperties[_p->first])
292         {
293             ++_p;
294         }
295         if(_p == _properties.end())
296         {
297             _server->updateRuntimePropertiesCallback(_desc);
298             return;
299         }
300 
301         Ice::PropertyDict oldProps = toPropertyDict(_oldProperties[_p->first]);
302         Ice::PropertyDict props = toPropertyDict(_p->second);
303         for(Ice::PropertyDict::const_iterator q = oldProps.begin(); q != oldProps.end(); ++q)
304         {
305             if(props.find(q->first) == props.end())
306             {
307                 props[q->first] = "";
308             }
309         }
310 
311         string facet;
312         if(_p->first == "config")
313         {
314             facet = "Properties";
315             if(_traceLevels->server > 1)
316             {
317                 const string id = _server->getId();
318                 Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
319                 out << "updating runtime properties for server `" << id << "'";
320             }
321         }
322         else
323         {
324             assert(_p->first.find("config_") == 0);
325             const string service = _p->first.substr(7);
326             if(getPropertyAsInt(_properties["config"], "IceBox.UseSharedCommunicator." + service) > 0)
327             {
328                 facet = "IceBox.SharedCommunicator.Properties";
329             }
330             else
331             {
332                 facet = "IceBox.Service." + service + ".Properties";
333             }
334             if(_traceLevels->server > 1)
335             {
336                 const string id = _server->getId();
337                 Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
338                 out << "updating runtime properties for service `" << service << "' from server `" + id + "'";
339             }
340         }
341 
342         //
343         // Increment the iterator *before* invoking setProperties_async to avoid a
344         // race condition.
345         //
346         ++_p;
347 
348         Ice::PropertiesAdminPrx p = Ice::PropertiesAdminPrx::uncheckedCast(_admin, facet);
349         p->begin_setProperties(props, Ice::newCallback_PropertiesAdmin_setProperties(this,
350                                                                                      &ResetPropertiesCB::next,
351                                                                                      &ResetPropertiesCB::exception));
352     }
353 
354     void
exception(const Ice::Exception & ex)355     exception(const Ice::Exception& ex)
356     {
357         _server->updateRuntimePropertiesCallback(ex, _desc);
358     }
359 
360     const ServerIPtr _server;
361     const Ice::ObjectPrx _admin;
362     const InternalServerDescriptorPtr _desc;
363     const TraceLevelsPtr _traceLevels;
364     PropertyDescriptorSeqDict _properties;
365     PropertyDescriptorSeqDict _oldProperties;
366     PropertyDescriptorSeqDict::const_iterator _p;
367 };
368 typedef IceUtil::Handle<ResetPropertiesCB> ResetPropertiesCBPtr;
369 
370 struct EnvironmentEval : std::unary_function<string, string>
371 {
372 
373     string
operator ()IceGrid::EnvironmentEval374     operator()(const std::string& value)
375     {
376         string::size_type assignment = value.find("=");
377         if(assignment == string::npos || assignment >= value.size() - 1)
378         {
379             return value;
380         }
381 
382         string v = value.substr(assignment + 1);
383         assert(v.size());
384         string::size_type beg = 0;
385         string::size_type end;
386 #ifdef _WIN32
387         vector<wchar_t> buf;
388         buf.resize(32767);
389         while((beg = v.find("%", beg)) != string::npos && beg < v.size() - 1)
390         {
391             end = v.find("%", beg + 1);
392             if(end == string::npos)
393             {
394                 break;
395             }
396             string variable = v.substr(beg + 1, end - beg - 1);
397             DWORD ret = GetEnvironmentVariableW(Ice::stringToWstring(variable).c_str(), &buf[0],
398                                                 static_cast<DWORD>(buf.size()));
399             string valstr = (ret > 0 && ret < buf.size()) ? Ice::wstringToString(&buf[0]) : string("");
400             v.replace(beg, end - beg + 1, valstr);
401             beg += valstr.size();
402         }
403 #else
404         while((beg = v.find("$", beg)) != string::npos && beg < v.size() - 1)
405         {
406             string variable;
407             if(v[beg + 1] == '{')
408             {
409                 end = v.find("}");
410                 if(end == string::npos)
411                 {
412                     break;
413                 }
414                 variable = v.substr(beg + 2, end - beg - 2);
415             }
416             else
417             {
418                 end = beg + 1;
419                 while((isalnum(static_cast<unsigned char>(v[end])) || v[end] == '_')  && end < v.size())
420                 {
421                     ++end;
422                 }
423                 variable = v.substr(beg + 1, end - beg - 1);
424                 --end;
425             }
426 
427             char* val = getenv(variable.c_str());
428             string valstr = val ? string(val) : "";
429             v.replace(beg, end - beg + 1, valstr);
430             beg += valstr.size();
431         }
432 #endif
433         return value.substr(0, assignment) + "=" + v;
434     }
435 
436 };
437 
438 }
439 
ServerCommand(const ServerIPtr & server)440 ServerCommand::ServerCommand(const ServerIPtr& server) : _server(server)
441 {
442 }
443 
~ServerCommand()444 ServerCommand::~ServerCommand()
445 {
446 }
447 
TimedServerCommand(const ServerIPtr & server,const IceUtil::TimerPtr & timer,int timeout)448 TimedServerCommand::TimedServerCommand(const ServerIPtr& server, const IceUtil::TimerPtr& timer, int timeout) :
449     ServerCommand(server), _timer(timer), _timeout(timeout)
450 {
451 }
452 
453 void
startTimer()454 TimedServerCommand::startTimer()
455 {
456     _timerTask = new CommandTimeoutTimerTask(this);
457     try
458     {
459         _timer->schedule(_timerTask, IceUtil::Time::seconds(_timeout));
460     }
461     catch(const IceUtil::Exception&)
462     {
463         // Ignore, timer is destroyed because node is shutting down.
464     }
465 }
466 
467 void
stopTimer()468 TimedServerCommand::stopTimer()
469 {
470     if(_timerTask)
471     {
472         _timer->cancel(_timerTask);
473         _timerTask = 0;
474     }
475 }
476 
LoadCommand(const ServerIPtr & server,const InternalServerDescriptorPtr & runtime,const TraceLevelsPtr & traceLevels)477 LoadCommand::LoadCommand(const ServerIPtr& server,
478                          const InternalServerDescriptorPtr& runtime,
479                          const TraceLevelsPtr& traceLevels) :
480     ServerCommand(server), _runtime(runtime), _updating(false), _traceLevels(traceLevels)
481 {
482 }
483 
484 bool
canExecute(ServerI::InternalServerState state)485 LoadCommand::canExecute(ServerI::InternalServerState state)
486 {
487     return state == ServerI::Inactive;
488 }
489 
490 ServerI::InternalServerState
nextState()491 LoadCommand::nextState()
492 {
493     return ServerI::Loading;
494 }
495 
496 void
execute()497 LoadCommand::execute()
498 {
499     _server->update();
500 }
501 
502 void
setUpdate(const InternalServerDescriptorPtr & descriptor,bool clearDir)503 LoadCommand::setUpdate(const InternalServerDescriptorPtr& descriptor, bool clearDir)
504 {
505     _clearDir = clearDir;
506     _desc = descriptor;
507 }
508 
509 InternalServerDescriptorPtr
getInternalServerDescriptor() const510 LoadCommand::getInternalServerDescriptor() const
511 {
512     return _desc;
513 }
514 
515 bool
clearDir() const516 LoadCommand::clearDir() const
517 {
518     return _clearDir;
519 }
520 
521 void
addCallback(const AMD_Node_loadServerPtr & amdCB)522 LoadCommand::addCallback(const AMD_Node_loadServerPtr& amdCB)
523 {
524     _loadCB.push_back(amdCB);
525 }
526 
527 void
startRuntimePropertiesUpdate(const Ice::ObjectPrx & process)528 LoadCommand::startRuntimePropertiesUpdate(const Ice::ObjectPrx& process)
529 {
530     if(_updating)
531     {
532         return;
533     }
534     assert(_desc != _runtime);
535     _updating = true;
536 
537     ResetPropertiesCBPtr cb = new ResetPropertiesCB(_server, process, _desc, _runtime, _traceLevels);
538     cb->execute();
539 }
540 
541 bool
finishRuntimePropertiesUpdate(const InternalServerDescriptorPtr & runtime,const Ice::ObjectPrx & process)542 LoadCommand::finishRuntimePropertiesUpdate(const InternalServerDescriptorPtr& runtime, const Ice::ObjectPrx& process)
543 {
544     _updating = false;
545     _runtime = runtime; // The new runtime server descriptor.
546 
547     if(_traceLevels->server > 0)
548     {
549         Ice::Trace out(_traceLevels->logger, _traceLevels->serverCat);
550         out << "updated runtime properties for server `" << _server->getId() << "'";
551     }
552 
553     if(_desc != _runtime)
554     {
555         startRuntimePropertiesUpdate(process);
556         return false;
557     }
558     else
559     {
560         return true;
561     }
562 }
563 
564 void
failed(const Ice::Exception & ex)565 LoadCommand::failed(const Ice::Exception& ex)
566 {
567     for(vector<AMD_Node_loadServerPtr>::const_iterator p = _loadCB.begin(); p != _loadCB.end(); ++p)
568     {
569         (*p)->ice_exception(ex);
570     }
571     _loadCB.clear();
572 }
573 
574 void
finished(const ServerPrx & proxy,const AdapterPrxDict & adapters,int at,int dt)575 LoadCommand::finished(const ServerPrx& proxy, const AdapterPrxDict& adapters, int at, int dt)
576 {
577     for(vector<AMD_Node_loadServerPtr>::const_iterator p = _loadCB.begin(); p != _loadCB.end(); ++p)
578     {
579         (*p)->ice_response(proxy, adapters, at, dt);
580     }
581     _loadCB.clear();
582 }
583 
DestroyCommand(const ServerIPtr & server,bool loadFailure,bool clearDir)584 DestroyCommand::DestroyCommand(const ServerIPtr& server, bool loadFailure, bool clearDir) :
585     ServerCommand(server),
586     _loadFailure(loadFailure),
587     _clearDir(clearDir)
588 {
589 }
590 
591 bool
canExecute(ServerI::InternalServerState state)592 DestroyCommand::canExecute(ServerI::InternalServerState state)
593 {
594     return state == ServerI::Inactive;
595 }
596 
597 ServerI::InternalServerState
nextState()598 DestroyCommand::nextState()
599 {
600     return ServerI::Destroying;
601 }
602 
603 void
execute()604 DestroyCommand::execute()
605 {
606     _server->destroy();
607 }
608 
609 void
addCallback(const AMD_Node_destroyServerPtr & amdCB)610 DestroyCommand::addCallback(const AMD_Node_destroyServerPtr& amdCB)
611 {
612     _destroyCB.push_back(amdCB);
613 }
614 
615 void
finished()616 DestroyCommand::finished()
617 {
618     for(vector<AMD_Node_destroyServerPtr>::const_iterator p = _destroyCB.begin(); p != _destroyCB.end(); ++p)
619     {
620         (*p)->ice_response();
621     }
622 }
623 
624 bool
loadFailure() const625 DestroyCommand::loadFailure() const
626 {
627     return _loadFailure;
628 }
629 
630 bool
clearDir() const631 DestroyCommand::clearDir() const
632 {
633     return _clearDir;
634 }
635 
PatchCommand(const ServerIPtr & server)636 PatchCommand::PatchCommand(const ServerIPtr& server) :
637     ServerCommand(server),
638     _notified(false),
639     _destroyed(false)
640 {
641 }
642 
643 bool
canExecute(ServerI::InternalServerState state)644 PatchCommand::canExecute(ServerI::InternalServerState state)
645 {
646     return state == ServerI::Inactive;
647 }
648 
649 ServerI::InternalServerState
nextState()650 PatchCommand::nextState()
651 {
652     return ServerI::Patching;
653 }
654 
655 void
execute()656 PatchCommand::execute()
657 {
658     Lock sync(*this);
659     _notified = true;
660     notifyAll();
661 }
662 
663 bool
waitForPatch()664 PatchCommand::waitForPatch()
665 {
666     Lock sync(*this);
667     while(!_notified && !_destroyed)
668     {
669         wait();
670     }
671     return _destroyed;
672 }
673 
674 void
destroyed()675 PatchCommand::destroyed()
676 {
677     Lock sync(*this);
678     _destroyed = true;
679     notifyAll();
680 }
681 
682 void
finished()683 PatchCommand::finished()
684 {
685 }
686 
StartCommand(const ServerIPtr & server,const IceUtil::TimerPtr & timer,int timeout)687 StartCommand::StartCommand(const ServerIPtr& server, const IceUtil::TimerPtr& timer, int timeout) :
688     TimedServerCommand(server, timer, timeout)
689 {
690 }
691 
692 bool
canExecute(ServerI::InternalServerState state)693 StartCommand::canExecute(ServerI::InternalServerState state)
694 {
695     return state == ServerI::Inactive;
696 }
697 
698 ServerI::InternalServerState
nextState()699 StartCommand::nextState()
700 {
701     startTimer();
702     return ServerI::Activating;
703 }
704 
705 void
execute()706 StartCommand::execute()
707 {
708     _server->activate();
709 }
710 
711 void
timeout()712 StartCommand::timeout()
713 {
714     _server->activationTimedOut();
715 }
716 
717 void
addCallback(const AMD_Server_startPtr & amdCB)718 StartCommand::addCallback(const AMD_Server_startPtr& amdCB)
719 {
720     _startCB.push_back(amdCB);
721 }
722 
723 void
failed(const string & reason)724 StartCommand::failed(const string& reason)
725 {
726     stopTimer();
727     ServerStartException ex(_server->getId(), reason);
728     for(vector<AMD_Server_startPtr>::const_iterator p = _startCB.begin(); p != _startCB.end(); ++p)
729     {
730         (*p)->ice_exception(ex);
731     }
732     _startCB.clear();
733 }
734 
735 void
finished()736 StartCommand::finished()
737 {
738     stopTimer();
739     for(vector<AMD_Server_startPtr>::const_iterator p = _startCB.begin(); p != _startCB.end(); ++p)
740     {
741         (*p)->ice_response();
742     }
743     _startCB.clear();
744 }
745 
StopCommand(const ServerIPtr & server,const IceUtil::TimerPtr & timer,int timeout,bool deactivate)746 StopCommand::StopCommand(const ServerIPtr& server, const IceUtil::TimerPtr& timer, int timeout, bool deactivate)
747     : TimedServerCommand(server, timer, timeout), _deactivate(deactivate)
748 {
749 }
750 
751 bool
isStopped(ServerI::InternalServerState state)752 StopCommand::isStopped(ServerI::InternalServerState state)
753 {
754     return state == ServerI::Inactive || state == ServerI::Patching || state == ServerI::Loading ||
755         state >= ServerI::Destroying;
756 }
757 
758 bool
canExecute(ServerI::InternalServerState state)759 StopCommand::canExecute(ServerI::InternalServerState state)
760 {
761     return state == ServerI::WaitForActivation || state == ServerI::ActivationTimeout || state == ServerI::Active;
762 }
763 
764 ServerI::InternalServerState
nextState()765 StopCommand::nextState()
766 {
767     startTimer();
768     return ServerI::Deactivating;
769 }
770 
771 void
execute()772 StopCommand::execute()
773 {
774     if(_deactivate)
775     {
776         _server->deactivate();
777     }
778 }
779 
780 void
timeout()781 StopCommand::timeout()
782 {
783     _server->kill();
784 }
785 
786 void
addCallback(const AMD_Server_stopPtr & amdCB)787 StopCommand::addCallback(const AMD_Server_stopPtr& amdCB)
788 {
789     _stopCB.push_back(amdCB);
790 }
791 
792 void
failed(const string & reason)793 StopCommand::failed(const string& reason)
794 {
795     stopTimer();
796     ServerStopException ex(_server->getId(), reason);
797     for(vector<AMD_Server_stopPtr>::const_iterator p = _stopCB.begin(); p != _stopCB.end(); ++p)
798     {
799         (*p)->ice_exception(ex);
800     }
801     _stopCB.clear();
802 }
803 
804 void
finished()805 StopCommand::finished()
806 {
807     stopTimer();
808     for(vector<AMD_Server_stopPtr>::const_iterator p = _stopCB.begin(); p != _stopCB.end(); ++p)
809     {
810         (*p)->ice_response();
811     }
812     _stopCB.clear();
813 }
814 
ServerI(const NodeIPtr & node,const ServerPrx & proxy,const string & serversDir,const string & id,int wt)815 ServerI::ServerI(const NodeIPtr& node, const ServerPrx& proxy, const string& serversDir, const string& id, int wt) :
816     _node(node),
817     _this(proxy),
818     _id(id),
819     _waitTime(wt),
820     _serverDir(serversDir + "/" + id),
821     _disableOnFailure(0),
822     _state(ServerI::Inactive),
823     _activation(ServerI::Disabled),
824     _failureTime(IceUtil::Time::now(IceUtil::Time::Monotonic)), // Ensure that _activation is init. in updateImpl().
825     _pid(0)
826 {
827     assert(_node->getActivator());
828     const_cast<int&>(_disableOnFailure) =
829         _node->getCommunicator()->getProperties()->getPropertyAsIntWithDefault("IceGrid.Node.DisableOnFailure", 0);
830 }
831 
~ServerI()832 ServerI::~ServerI()
833 {
834 }
835 
836 void
waitForApplicationUpdateCompleted(const Ice::AsyncResultPtr &)837 ServerI::waitForApplicationUpdateCompleted(const Ice::AsyncResultPtr&)
838 {
839     activate();
840 }
841 
842 void
start_async(const AMD_Server_startPtr & amdCB,const Ice::Current &)843 ServerI::start_async(const AMD_Server_startPtr& amdCB, const Ice::Current&)
844 {
845     start(Manual, amdCB);
846 }
847 
848 void
stop_async(const AMD_Server_stopPtr & amdCB,const Ice::Current &)849 ServerI::stop_async(const AMD_Server_stopPtr& amdCB, const Ice::Current&)
850 {
851     ServerCommandPtr command;
852     {
853         Lock sync(*this);
854         checkDestroyed();
855 
856         if(StopCommand::isStopped(_state))
857         {
858             throw ServerStopException(_id, "The server is already inactive.");
859         }
860         else if(_state == Destroying)
861         {
862             throw ServerStopException(_id, "The server is being destroyed.");
863         }
864 
865         if(!_stop)
866         {
867             _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
868         }
869         if(amdCB)
870         {
871             _stop->addCallback(amdCB);
872         }
873         command = nextCommand();
874     }
875     if(command)
876     {
877         command->execute();
878     }
879 }
880 
881 void
sendSignal(const string & signal,const Ice::Current &)882 ServerI::sendSignal(const string& signal, const Ice::Current&)
883 {
884     _node->getActivator()->sendSignal(_id, signal);
885 }
886 
887 void
writeMessage(const string & message,Ice::Int fd,const Ice::Current &)888 ServerI::writeMessage(const string& message, Ice::Int fd, const Ice::Current&)
889 {
890     Lock sync(*this);
891     checkDestroyed();
892     if(_process != 0)
893     {
894         try
895         {
896             _process->writeMessage(message, fd);
897         }
898         catch(const Ice::LocalException&)
899         {
900         }
901     }
902 }
903 
904 ServerState
getState(const Ice::Current &) const905 ServerI::getState(const Ice::Current&) const
906 {
907     Lock sync(*this);
908     checkDestroyed();
909     return toServerState(_state);
910 }
911 
912 Ice::Int
getPid(const Ice::Current &) const913 ServerI::getPid(const Ice::Current&) const
914 {
915     return _node->getActivator()->getServerPid(_id);
916 }
917 
918 Ice::ObjectPrx
getProcess() const919 ServerI::getProcess() const
920 {
921     Lock sync(*this);
922 
923     if(_process == 0 || _state <= Inactive || _state >= Deactivating)
924     {
925         return 0;
926     }
927     else
928     {
929         return _process;
930     }
931 }
932 
933 void
setEnabled(bool enabled,const::Ice::Current &)934 ServerI::setEnabled(bool enabled, const ::Ice::Current&)
935 {
936     bool activate = false;
937     ServerAdapterDict adpts;
938     {
939         Lock sync(*this);
940         checkDestroyed();
941         assert(_desc);
942 
943         if(enabled && _activation == Disabled)
944         {
945             _failureTime = IceUtil::Time();
946             _activation = toServerActivation(_desc->activation);
947             activate = _state == Inactive && _activation == Always;
948         }
949         else if(!enabled && (_activation != Disabled || _failureTime != IceUtil::Time()))
950         {
951             _failureTime = IceUtil::Time();
952             _activation = Disabled;
953             if(_timerTask)
954             {
955                 _node->getTimer()->cancel(_timerTask);
956                 _timerTask = 0;
957             }
958         }
959         else
960         {
961             return; // Nothing to change!
962         }
963 
964         adpts = _adapters;
965         _node->observerUpdateServer(getDynamicInfo());
966     }
967 
968     for(ServerAdapterDict::iterator r = adpts.begin(); r != adpts.end(); ++r)
969     {
970         r->second->updateEnabled();
971     }
972 
973     if(activate)
974     {
975         try
976         {
977             start(Always);
978         }
979         catch(const ServerStartException& ex)
980         {
981             Ice::Error out(_node->getTraceLevels()->logger);
982             out << "couldn't reactivate server `" << _id << "' with `always' activation mode:\n"
983                 << ex.reason;
984         }
985         catch(const Ice::ObjectNotExistException&)
986         {
987         }
988     }
989 }
990 
991 bool
isEnabled(const::Ice::Current &) const992 ServerI::isEnabled(const ::Ice::Current&) const
993 {
994     Lock sync(*this);
995     checkDestroyed();
996     return _activation != Disabled;
997 }
998 
999 void
setProcess_async(const AMD_Server_setProcessPtr & amdCB,const Ice::ProcessPrx & process,const Ice::Current &)1000 ServerI::setProcess_async(const AMD_Server_setProcessPtr& amdCB, const Ice::ProcessPrx& process, const Ice::Current&)
1001 {
1002     bool deact = false;
1003     ServerAdapterDict adpts;
1004     ServerCommandPtr command;
1005     {
1006         Lock sync(*this);
1007         checkDestroyed();
1008         _process = process;
1009         if(_state == DeactivatingWaitForProcess)
1010         {
1011             deact = true;
1012         }
1013         else
1014         {
1015             if(checkActivation())
1016             {
1017                 adpts = _adapters;
1018             }
1019             command = nextCommand();
1020         }
1021     }
1022     amdCB->ice_response();
1023 
1024     for(ServerAdapterDict::iterator r = adpts.begin(); r != adpts.end(); ++r)
1025     {
1026         try
1027         {
1028             r->second->activationCompleted();
1029         }
1030         catch(const Ice::ObjectNotExistException&)
1031         {
1032         }
1033     }
1034 
1035     if(deact)
1036     {
1037         deactivate();
1038     }
1039 
1040     if(command)
1041     {
1042         command->execute();
1043     }
1044 }
1045 
1046 Ice::Long
getOffsetFromEnd(const string & filename,int count,const Ice::Current &) const1047 ServerI::getOffsetFromEnd(const string& filename, int count, const Ice::Current&) const
1048 {
1049     return _node->getFileCache()->getOffsetFromEnd(getFilePath(filename), count);
1050 }
1051 
1052 bool
read(const string & filename,Ice::Long pos,int size,Ice::Long & newPos,Ice::StringSeq & lines,const Ice::Current &) const1053 ServerI::read(const string& filename, Ice::Long pos, int size, Ice::Long& newPos, Ice::StringSeq& lines,
1054               const Ice::Current&) const
1055 {
1056     return _node->getFileCache()->read(getFilePath(filename), pos, size, newPos, lines);
1057 }
1058 
1059 bool
isAdapterActivatable(const string & id) const1060 ServerI::isAdapterActivatable(const string& id) const
1061 {
1062     Lock sync(*this);
1063     if(!_desc || _activation == Disabled)
1064     {
1065         return false;
1066     }
1067 
1068     if(_desc->activation == "manual" ||
1069        (_desc->activation == "session" && _desc->sessionId.empty()))
1070     {
1071         return false;
1072     }
1073 
1074     if(_state <= WaitForActivation)
1075     {
1076         if(_activatedAdapters.find(id) != _activatedAdapters.end())
1077         {
1078             return false; // The adapter was already activated once.
1079         }
1080         return true;
1081     }
1082     else if(_state < Deactivating)
1083     {
1084         return false; // The server is active or its activation timed out.
1085     }
1086     else if(_state < Destroying)
1087     {
1088         return _node->getActivator()->isActive(); // The server is being deactivated and the
1089                                                   // node isn't shutting down yet.
1090     }
1091     else
1092     {
1093         return false;
1094     }
1095 }
1096 
1097 const string&
getId() const1098 ServerI::getId() const
1099 {
1100     return _id;
1101 }
1102 
1103 InternalDistributionDescriptorPtr
getDistribution() const1104 ServerI::getDistribution() const
1105 {
1106     Lock sync(*this);
1107     return _desc ? _desc->distrib : InternalDistributionDescriptorPtr();
1108 }
1109 
1110 bool
dependsOnApplicationDistrib() const1111 ServerI::dependsOnApplicationDistrib() const
1112 {
1113     Lock sync(*this);
1114     return _desc ? _desc->applicationDistrib : false;
1115 }
1116 
1117 void
start(ServerActivation activation,const AMD_Server_startPtr & amdCB)1118 ServerI::start(ServerActivation activation, const AMD_Server_startPtr& amdCB)
1119 {
1120     ServerCommandPtr command;
1121     {
1122         Lock sync(*this);
1123         checkDestroyed();
1124 
1125         //
1126         // Eventually re-enable the server if it's disabled because of a failure.
1127         //
1128         if(_disableOnFailure > 0 && _failureTime != IceUtil::Time())
1129         {
1130             if(activation == Manual ||
1131                (_failureTime + IceUtil::Time::seconds(_disableOnFailure) <
1132                 IceUtil::Time::now(IceUtil::Time::Monotonic)))
1133             {
1134                 _activation = _previousActivation;
1135                 _failureTime = IceUtil::Time();
1136             }
1137         }
1138 
1139         //
1140         // Check the current activation mode and the requested activation.
1141         //
1142         if(_activation == Disabled)
1143         {
1144             throw ServerStartException(_id, "The server is disabled.");
1145         }
1146         else if(_activation != Always && activation == Always)
1147         {
1148             assert(!amdCB);
1149             return; // Nothing to do.
1150         }
1151         else if(_activation == Manual && activation != Manual)
1152         {
1153             throw ServerStartException(_id, "The server activation doesn't allow this activation mode.");
1154         }
1155         else if(_activation == Session && _desc->sessionId.empty())
1156         {
1157             throw ServerStartException(_id, "The server is not owned by a session.");
1158         }
1159 
1160         //
1161         // Check the current state.
1162         //
1163         if(_state == ActivationTimeout)
1164         {
1165             throw ServerStartException(_id, "The server activation timed out.");
1166         }
1167         else if(_state == Active)
1168         {
1169             if(activation == Always)
1170             {
1171                 return; // Nothing to do, it's already active (and we
1172                         // don't want to throw because it would be
1173                         // considered as an error.)
1174             }
1175             throw ServerStartException(_id, "The server is already active.");
1176         }
1177         else if(_state == Destroying)
1178         {
1179             throw ServerStartException(_id, "The server is being destroyed.");
1180         }
1181 
1182         if(_timerTask)
1183         {
1184             _node->getTimer()->cancel(_timerTask);
1185             _timerTask = 0;
1186         }
1187 
1188         if(!_start)
1189         {
1190             _start = new StartCommand(this, _node->getTimer(), _activationTimeout);
1191         }
1192         if(amdCB)
1193         {
1194             _start->addCallback(amdCB);
1195         }
1196         command = nextCommand();
1197     }
1198     if(command)
1199     {
1200         command->execute();
1201     }
1202 }
1203 
1204 ServerCommandPtr
load(const AMD_Node_loadServerPtr & amdCB,const InternalServerDescriptorPtr & desc,const string & replicaName,bool noRestart)1205 ServerI::load(const AMD_Node_loadServerPtr& amdCB, const InternalServerDescriptorPtr& desc, const string& replicaName,
1206               bool noRestart)
1207 {
1208     Lock sync(*this);
1209     checkDestroyed();
1210     checkRevision(replicaName, desc->uuid, desc->revision);
1211 
1212     //
1213     // Otherwise, if the following conditions are met:
1214     //
1215     // - the server is already loaded.
1216     // - the descriptor is from the master and the session id didn't change or it's coming from a slave.
1217     // - the descriptor is the same as the one loaded.
1218     //
1219     // we don't re-load the server. We just return the server
1220     // proxy and the proxies of its adapters.
1221     //
1222     InternalServerDescriptorPtr d = _load ? _load->getInternalServerDescriptor() : _desc;
1223     if(d && (replicaName != "Master" || d->sessionId == desc->sessionId) && !descriptorUpdated(d, desc))
1224     {
1225         if(d->revision != desc->revision)
1226         {
1227             updateRevision(desc->uuid, desc->revision);
1228         }
1229 
1230         if(!_desc || (_load && descriptorUpdated(_load->getInternalServerDescriptor(), _desc)))
1231         {
1232             //
1233             // If the server initial loading didn't complete yet or there's a new updated descriptor
1234             // waiting to be loaded, we wait for the loading to complete before replying.
1235             //
1236             _load->addCallback(amdCB);
1237             return 0;
1238         }
1239         else if(amdCB)
1240         {
1241             AdapterPrxDict adapters;
1242             for(ServerAdapterDict::const_iterator p = _adapters.begin(); p != _adapters.end(); ++p)
1243             {
1244                 adapters.insert(make_pair(p->first, p->second->getProxy()));
1245             }
1246             amdCB->ice_response(_this, adapters, _activationTimeout, _deactivationTimeout);
1247         }
1248         return 0;
1249     }
1250 
1251     if(!StopCommand::isStopped(_state) && !_stop) // Server is running and no stop is scheduled
1252     {
1253         assert(_desc);
1254         if(noRestart)
1255         {
1256             //
1257             // If the server is not inactive, we have to make sure the update doesn't require
1258             // a restart. If it requires a restart, we throw. Otherwise we update its properties
1259             // now.
1260             //
1261             checkNoRestart(desc);
1262         }
1263         else
1264         {
1265             _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
1266         }
1267     }
1268 
1269     if(!_load)
1270     {
1271         _load = new LoadCommand(this, _desc, _node->getTraceLevels());
1272     }
1273     _load->setUpdate(desc, _destroy);
1274     if(_destroy && _state != Destroying)
1275     {
1276         _destroy->finished();
1277         _destroy = 0;
1278     }
1279 
1280     if(_stop || StopCommand::isStopped(_state))
1281     {
1282         _load->addCallback(amdCB); // Load will return once the server is loaded.
1283     }
1284     else
1285     {
1286         if(_state >= ServerI::Activating && _state < ServerI::Active)
1287         {
1288             //
1289             // If the server is being activated, return the response
1290             // now. We can't wait for runtime properties to be updated
1291             // as this could cause a deadlock if the registry needs
1292             // the server proxy to register the server process proxy
1293             // with the node.
1294             //
1295             AdapterPrxDict adapters;
1296             for(ServerAdapterDict::const_iterator p = _adapters.begin(); p != _adapters.end(); ++p)
1297             {
1298                 adapters.insert(make_pair(p->first, p->second->getProxy()));
1299             }
1300             amdCB->ice_response(_this, adapters, _activationTimeout, _deactivationTimeout);
1301         }
1302         else if(_state == ServerI::Active)
1303         {
1304             _load->addCallback(amdCB); // Must be called before startRuntimePropertiesUpdate!
1305             updateRevision(desc->uuid, desc->revision);
1306             _load->startRuntimePropertiesUpdate(_process);
1307         }
1308         else
1309         {
1310             _load->addCallback(amdCB);
1311         }
1312     }
1313     return nextCommand();
1314 }
1315 
1316 bool
checkUpdate(const InternalServerDescriptorPtr & desc,bool noRestart,const Ice::Current &)1317 ServerI::checkUpdate(const InternalServerDescriptorPtr& desc, bool noRestart, const Ice::Current&)
1318 {
1319     Lock sync(*this);
1320     checkDestroyed();
1321 
1322     if(!_desc)
1323     {
1324         throw DeploymentException("server not loaded");
1325     }
1326 
1327     if(!desc)
1328     {
1329         if(noRestart && !StopCommand::isStopped(_state) && !_stop)
1330         {
1331             throw DeploymentException("the server is running");
1332         }
1333         return true;
1334     }
1335 
1336     InternalServerDescriptorPtr d = _load ? _load->getInternalServerDescriptor() : _desc;
1337     if(!descriptorUpdated(d, desc))
1338     {
1339         return StopCommand::isStopped(_state);
1340     }
1341 
1342     if(noRestart)
1343     {
1344         checkNoRestart(desc);
1345     }
1346 
1347     try
1348     {
1349         checkAndUpdateUser(desc, false); // false = don't update the user, just check.
1350     }
1351     catch(const exception& ex)
1352     {
1353         throw DeploymentException(ex.what());
1354     }
1355 
1356     return StopCommand::isStopped(_state);
1357 }
1358 
1359 void
checkRemove(bool noRestart,const Ice::Current &)1360 ServerI::checkRemove(bool noRestart, const Ice::Current&)
1361 {
1362     Lock sync(*this);
1363     checkDestroyed();
1364 
1365     if(noRestart && !StopCommand::isStopped(_state) && !_stop)
1366     {
1367         throw DeploymentException("the server is running");
1368     }
1369 }
1370 
1371 ServerCommandPtr
destroy(const AMD_Node_destroyServerPtr & amdCB,const string & uuid,int revision,const string & replicaName,bool noRestart)1372 ServerI::destroy(const AMD_Node_destroyServerPtr& amdCB, const string& uuid, int revision, const string& replicaName,
1373                  bool noRestart)
1374 {
1375     Lock sync(*this);
1376     checkDestroyed();
1377     checkRevision(replicaName, uuid, revision);
1378 
1379     if(!_desc)
1380     {
1381         amdCB->ice_response();
1382         return 0; // Server is already destroyed.
1383     }
1384 
1385     if(!StopCommand::isStopped(_state) && !_stop)
1386     {
1387         if(noRestart)
1388         {
1389             throw DeploymentException("removal requires server to be stopped");
1390         }
1391         _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
1392     }
1393 
1394     if(!_destroy)
1395     {
1396         //
1397         // If uuid is empty, the destroy call comes from the consistency check. In
1398         // this case, we clear the server directory only if it contains non-user data.
1399         //
1400         _destroy = new DestroyCommand(this, false, !uuid.empty());
1401     }
1402     if(amdCB)
1403     {
1404         _destroy->addCallback(amdCB);
1405     }
1406     return nextCommand();
1407 }
1408 
1409 bool
startPatch(bool shutdown)1410 ServerI::startPatch(bool shutdown)
1411 {
1412     ServerCommandPtr command;
1413     {
1414         Lock sync(*this);
1415         checkDestroyed();
1416         if(!StopCommand::isStopped(_state))
1417         {
1418             if(!shutdown)
1419             {
1420                 return false;
1421             }
1422             else if(!_stop)
1423             {
1424                 _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout);
1425             }
1426         }
1427         if(!_patch)
1428         {
1429             _patch = new PatchCommand(this);
1430         }
1431         command = nextCommand();
1432     }
1433     if(command)
1434     {
1435         command->execute();
1436     }
1437     return true;
1438 }
1439 
1440 bool
waitForPatch()1441 ServerI::waitForPatch()
1442 {
1443     PatchCommandPtr patch;
1444     {
1445         Lock sync(*this);
1446         if(!_patch)
1447         {
1448             return true;
1449         }
1450         patch = _patch;
1451     }
1452     return patch->waitForPatch();
1453 }
1454 
1455 void
finishPatch()1456 ServerI::finishPatch()
1457 {
1458 #ifndef _WIN32
1459     {
1460         Lock sync(*this);
1461         try
1462         {
1463             chownRecursive(_serverDir + "/distrib", _uid, _gid);
1464         }
1465         catch(const exception& ex)
1466         {
1467             Ice::Warning out(_node->getTraceLevels()->logger);
1468             out << ex.what();
1469         }
1470     }
1471 #endif
1472     setState(ServerI::Inactive);
1473 }
1474 
1475 void
adapterActivated(const string & id)1476 ServerI::adapterActivated(const string& id)
1477 {
1478     ServerCommandPtr command;
1479     ServerAdapterDict adpts;
1480     {
1481         Lock sync(*this);
1482         if(_state != ServerI::Activating &&
1483            _state != ServerI::WaitForActivation &&
1484            _state != ServerI::ActivationTimeout)
1485         {
1486             return;
1487         }
1488         _activatedAdapters.insert(id);
1489         if(checkActivation())
1490         {
1491             adpts = _adapters;
1492         }
1493         command = nextCommand();
1494     }
1495     for(ServerAdapterDict::iterator r = adpts.begin(); r != adpts.end(); ++r)
1496     {
1497         if(r->first != id)
1498         {
1499             try
1500             {
1501                 r->second->activationCompleted();
1502             }
1503             catch(const Ice::ObjectNotExistException&)
1504             {
1505             }
1506         }
1507     }
1508     if(command)
1509     {
1510         command->execute();
1511     }
1512 }
1513 
1514 void
adapterDeactivated(const string & id)1515 ServerI::adapterDeactivated(const string& id)
1516 {
1517     ServerCommandPtr command;
1518     {
1519         Lock sync(*this);
1520         while(_state == ServerI::Activating)
1521         {
1522             wait(); // Wait for activate() to set the state to WaitForActivation
1523         }
1524 
1525         if((_state == Active || _state == WaitForActivation) &&
1526            _serverLifetimeAdapters.find(id) != _serverLifetimeAdapters.end())
1527         {
1528             _stop = new StopCommand(this, _node->getTimer(), _deactivationTimeout, false);
1529         }
1530         command = nextCommand();
1531     }
1532     if(command)
1533     {
1534         command->execute();
1535     }
1536 }
1537 
1538 void
checkDestroyed() const1539 ServerI::checkDestroyed() const
1540 {
1541     if(_state == Destroyed)
1542     {
1543         throw Ice::ObjectNotExistException(__FILE__, __LINE__, _this->ice_getIdentity(), "", "");
1544     }
1545 }
1546 
1547 void
disableOnFailure()1548 ServerI::disableOnFailure()
1549 {
1550     //
1551     // If the server is already disabled, nothing to do.
1552     //
1553     if(_activation == Disabled)
1554     {
1555         return;
1556     }
1557 
1558     //
1559     // If disable on failure is configured or if the activation mode
1560     // is always and the server wasn't active at the time of the
1561     // failure we disable the server.
1562     //
1563     if(_disableOnFailure != 0 || (_activation == Always && (_state == Activating || _state == WaitForActivation)))
1564     {
1565         _previousActivation = _activation;
1566         _activation = Disabled;
1567         _failureTime = IceUtil::Time::now(IceUtil::Time::Monotonic);
1568     }
1569 }
1570 
1571 void
activationTimedOut()1572 ServerI::activationTimedOut()
1573 {
1574     ServerCommandPtr command;
1575     ServerAdapterDict adapters;
1576     {
1577         Lock sync(*this);
1578         if(_state != ServerI::WaitForActivation)
1579         {
1580             return;
1581         }
1582 
1583         setStateNoSync(ServerI::ActivationTimeout, "The server activation timed out.");
1584 
1585         if(_node->getTraceLevels()->server > 1)
1586         {
1587             Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
1588             out << "server `" << _id << "' activation timed out";
1589         }
1590         adapters = _adapters;
1591         command = nextCommand();
1592     }
1593 
1594     for(ServerAdapterDict::const_iterator p = adapters.begin(); p != adapters.end(); ++p)
1595     {
1596         try
1597         {
1598             p->second->activationFailed("server activation timed out");
1599         }
1600         catch(const Ice::ObjectNotExistException&)
1601         {
1602         }
1603     }
1604 
1605     if(command)
1606     {
1607         command->execute();
1608     }
1609 }
1610 
1611 void
activate()1612 ServerI::activate()
1613 {
1614     InternalServerDescriptorPtr desc;
1615     ServerAdapterDict adpts;
1616     bool waitForReplication;
1617 
1618 #ifndef _WIN32
1619     uid_t uid;
1620     gid_t gid;
1621 #endif
1622     string failure;
1623     try
1624     {
1625         {
1626             Lock sync(*this);
1627             assert(_state == Activating && _desc);
1628             desc = _desc;
1629             adpts = _adapters;
1630 
1631             if(_activation == Disabled)
1632             {
1633                 throw runtime_error("The server is disabled.");
1634             }
1635 
1636             //
1637             // The first time the server is started, we ensure that the
1638             // replication of its descriptor is completed. This is to make
1639             // sure all the replicas are up to date when the server
1640             // starts for the first time with a given descriptor.
1641             //
1642             waitForReplication = _waitForReplication;
1643             _waitForReplication = false;
1644 
1645             _process = 0;
1646 
1647 #ifndef _WIN32
1648             uid = _uid;
1649             gid = _gid;
1650 #endif
1651         }
1652 
1653         //
1654         // We first ensure that the application is replicated on all the
1655         // registries before to start the server. We only do this each
1656         // time the server is updated or initialy loaded on the node.
1657         //
1658         if(waitForReplication)
1659         {
1660             NodeSessionPrx session = _node->getMasterNodeSession();
1661             if(session)
1662             {
1663                 _node->getMasterNodeSession()->begin_waitForApplicationUpdate(
1664                     desc->uuid, desc->revision, ::Ice::newCallback(this, &ServerI::waitForApplicationUpdateCompleted));
1665                 return;
1666             }
1667         }
1668 
1669         //
1670         // Compute the server command line options.
1671         //
1672         Ice::StringSeq options;
1673         for(Ice::StringSeq::const_iterator p = desc->options.begin(); p != desc->options.end(); ++p)
1674         {
1675             if(!p->empty())
1676             {
1677                 options.push_back(*p);
1678             }
1679         }
1680         options.push_back("--Ice.Config=" + escapeProperty(_serverDir + "/config/config"));
1681 
1682         Ice::StringSeq envs;
1683         transform(desc->envs.begin(), desc->envs.end(), back_inserter(envs), EnvironmentEval());
1684 
1685         //
1686         // Clear the adapters direct proxy (this is usefull if the server
1687         // was manually activated).
1688         //
1689         for(ServerAdapterDict::iterator p = adpts.begin(); p != adpts.end(); ++p)
1690         {
1691             try
1692             {
1693                 p->second->clear();
1694             }
1695             catch(const Ice::ObjectNotExistException&)
1696             {
1697             }
1698         }
1699 
1700 #ifndef _WIN32
1701         int pid = _node->getActivator()->activate(desc->id, desc->exe, desc->pwd, uid, gid, options, envs, this);
1702 #else
1703         int pid = _node->getActivator()->activate(desc->id, desc->exe, desc->pwd, options, envs, this);
1704 #endif
1705         ServerCommandPtr command;
1706         bool active = false;
1707         {
1708             Lock sync(*this);
1709             assert(_state == Activating);
1710             _pid = pid;
1711             setStateNoSync(ServerI::WaitForActivation);
1712             active = checkActivation();
1713             command = nextCommand();
1714             notifyAll(); // Terminated might be waiting for the state change.
1715         }
1716         if(active)
1717         {
1718             for(ServerAdapterDict::iterator r = adpts.begin(); r != adpts.end(); ++r)
1719             {
1720                 try
1721                 {
1722                     r->second->activationCompleted();
1723                 }
1724                 catch(const Ice::ObjectNotExistException&)
1725                 {
1726                 }
1727             }
1728         }
1729         if(command)
1730         {
1731             command->execute();
1732         }
1733         return;
1734     }
1735     catch(const Ice::Exception& ex)
1736     {
1737         Ice::Warning out(_node->getTraceLevels()->logger);
1738         out << "activation failed for server `" << _id << "':\n";
1739         out << ex;
1740 
1741         failure = ex.what();
1742     }
1743     catch(const std::exception& ex)
1744     {
1745         failure = ex.what();
1746     }
1747 
1748     {
1749         Lock sync(*this);
1750         disableOnFailure();
1751         setStateNoSync(ServerI::Deactivating, failure);
1752     }
1753 
1754     for(ServerAdapterDict::iterator r = adpts.begin(); r != adpts.end(); ++r)
1755     {
1756         try
1757         {
1758             r->second->activationFailed(failure);
1759         }
1760         catch(const Ice::ObjectNotExistException&)
1761         {
1762         }
1763     }
1764 
1765     setState(ServerI::Inactive);
1766 }
1767 
1768 void
kill()1769 ServerI::kill()
1770 {
1771     {
1772         Lock sync(*this);
1773         if(_state != Destroying && _state != Deactivating && _state != DeactivatingWaitForProcess)
1774         {
1775             return;
1776         }
1777     }
1778 
1779     try
1780     {
1781         _node->getActivator()->kill(_id);
1782     }
1783     catch(const Ice::SyscallException& ex)
1784     {
1785         Ice::Warning out(_node->getTraceLevels()->logger);
1786         out << "deactivation failed for server `" << _id << "':\n";
1787         out << ex;
1788         setState(ServerI::Inactive); // TODO: Is this really correct?
1789     }
1790 }
1791 
1792 void
deactivate()1793 ServerI::deactivate()
1794 {
1795     Ice::ProcessPrx process;
1796     {
1797         Lock sync(*this);
1798         if(_state != Deactivating && _state != DeactivatingWaitForProcess)
1799         {
1800             return;
1801         }
1802 
1803         assert(_desc);
1804 
1805         //
1806         // If a process object is supposed to be registered and it's
1807         // not set yet, we wait for the server to set this process
1808         // object before attempting to deactivate the server again.
1809         //
1810         if(_desc->processRegistered && !_process)
1811         {
1812             setStateNoSync(ServerI::DeactivatingWaitForProcess);
1813             return;
1814         }
1815         process = _process;
1816     }
1817 
1818     try
1819     {
1820         //
1821         // Deactivate the server and for the termination of the server.
1822         //
1823         _node->getActivator()->deactivate(_id, process);
1824         return;
1825     }
1826     catch(const Ice::Exception& ex)
1827     {
1828         Ice::Warning out(_node->getTraceLevels()->logger);
1829         out << "graceful server shutdown failed, killing server `" << _id << "':\n";
1830         out << ex;
1831     }
1832 
1833     try
1834     {
1835         //
1836         // If we couldn't deactivate it we kill it.
1837         //
1838         _node->getActivator()->kill(_id);
1839         return;
1840     }
1841     catch(const Ice::SyscallException& ex)
1842     {
1843         Ice::Warning out(_node->getTraceLevels()->logger);
1844         out << "deactivation failed for server `" << _id << "':\n";
1845         out << ex;
1846         setState(ServerI::Inactive); // TODO: Is this really correct?
1847     }
1848 }
1849 
1850 void
destroy()1851 ServerI::destroy()
1852 {
1853     ServerAdapterDict adpts;
1854     {
1855         Lock sync(*this);
1856         assert(_desc);
1857         assert(_state == Destroying);
1858         adpts = _adapters;
1859     }
1860 
1861     _node->removeServer(this, _desc->application);
1862 
1863     //
1864     // Remove the server directory only if the clear dir flag is set (user
1865     // explicitly destroyed the server) or if the server directory doesn't
1866     // contain user data).
1867     //
1868     if(_destroy->clearDir() || _node->canRemoveServerDirectory(_id))
1869     {
1870         try
1871         {
1872             IcePatch2Internal::removeRecursive(_serverDir);
1873         }
1874         catch(const exception& ex)
1875         {
1876             if(!_destroy->loadFailure())
1877             {
1878                 Ice::Warning out(_node->getTraceLevels()->logger);
1879                 out << "removing server directory `" << _serverDir << "' failed:\n" << ex.what();
1880             }
1881         }
1882     }
1883 
1884     //
1885     // Destroy the object adapters.
1886     //
1887     for(ServerAdapterDict::const_iterator p = adpts.begin(); p != adpts.end(); ++p)
1888     {
1889         try
1890         {
1891             p->second->destroy();
1892         }
1893         catch(const Ice::LocalException&)
1894         {
1895         }
1896     }
1897 
1898     setState(Destroyed);
1899 }
1900 
1901 void
terminated(const string & msg,int status)1902 ServerI::terminated(const string& msg, int status)
1903 {
1904     ServerAdapterDict adpts;
1905     {
1906         Lock sync(*this);
1907         while(_state == ServerI::Activating)
1908         {
1909             wait(); // Wait for activate() to set the state to WaitForActivation
1910         }
1911 
1912         adpts = _adapters;
1913         _activatedAdapters.clear();
1914         _pid = 0;
1915 
1916         bool failed = false;
1917 #ifndef _WIN32
1918         failed = WIFEXITED(status) && WEXITSTATUS(status) != 0;
1919         if(WIFSIGNALED(status))
1920         {
1921             int s = WTERMSIG(status);
1922             failed = s == SIGABRT || s == SIGILL || s == SIGBUS || s == SIGFPE || s == SIGSEGV;
1923         }
1924 #else
1925         failed = status != 0;
1926 #endif
1927         if(failed)
1928         {
1929             disableOnFailure();
1930         }
1931 
1932         if(_state != ServerI::Deactivating &&
1933            _state != ServerI::DeactivatingWaitForProcess &&
1934            _state != ServerI::Destroying)
1935         {
1936             ostringstream os;
1937             os << "The server terminated unexpectedly";
1938 #ifndef _WIN32
1939             if(WIFEXITED(status))
1940             {
1941                 os << " with exit code " << WEXITSTATUS(status);
1942             }
1943             else if(WIFSIGNALED(status))
1944             {
1945                 os << " with signal " << signalToString(WTERMSIG(status));
1946             }
1947 #else
1948             os << " with exit code " << status;
1949 #endif
1950             os << (msg.empty() ? string(".") : ":\n" + msg);
1951             setStateNoSync(ServerI::Deactivating, os.str());
1952         }
1953     }
1954 
1955     //
1956     // The server has terminated, set its adapter direct proxies to
1957     // null to cause the server re-activation if one of its adapter
1958     // direct proxy is requested.
1959     //
1960     for(ServerAdapterDict::iterator p = adpts.begin(); p != adpts.end(); ++p)
1961     {
1962         try
1963         {
1964             p->second->setDirectProxy(0, Ice::emptyCurrent);
1965         }
1966         catch(const Ice::ObjectNotExistException&)
1967         {
1968         }
1969     }
1970 
1971     bool doDestroy = false;
1972     ServerCommandPtr command;
1973     {
1974         Lock sync(*this);
1975         if(_state == ServerI::Destroying)
1976         {
1977             doDestroy = true;
1978         }
1979         else
1980         {
1981             setStateNoSync(ServerI::Inactive);
1982             command = nextCommand();
1983         }
1984     }
1985     if(doDestroy)
1986     {
1987         destroy();
1988     }
1989     else if(command)
1990     {
1991         command->execute();
1992     }
1993 }
1994 
1995 void
shutdown()1996 ServerI::shutdown()
1997 {
1998     Lock sync(*this);
1999     assert(_state == ServerI::Inactive);
2000     assert(!_destroy);
2001     assert(!_stop);
2002     assert(!_load);
2003     assert(!_patch);
2004     assert(!_start);
2005     _timerTask = 0;
2006 }
2007 
2008 void
update()2009 ServerI::update()
2010 {
2011     ServerCommandPtr command;
2012     {
2013         Lock sync(*this);
2014         if(_state != ServerI::Loading)
2015         {
2016             return;
2017         }
2018 
2019         InternalServerDescriptorPtr oldDescriptor = _desc;
2020         bool disabled = oldDescriptor && _activation == Disabled;
2021         try
2022         {
2023             if(_load->clearDir())
2024             {
2025                 //
2026                 // The server was explicitely destroyed then updated,
2027                 // we first need to cleanup the directory to remove
2028                 // any user created files.
2029                 //
2030                 try
2031                 {
2032                     IcePatch2Internal::removeRecursive(_serverDir);
2033                 }
2034                 catch(const exception&)
2035                 {
2036                 }
2037             }
2038 
2039             try
2040             {
2041                 updateImpl(_load->getInternalServerDescriptor());
2042             }
2043             catch(const exception& ex)
2044             {
2045                 throw DeploymentException(ex.what());
2046             }
2047 
2048             if(oldDescriptor)
2049             {
2050                 if(oldDescriptor->application != _desc->application)
2051                 {
2052                     _node->removeServer(this, oldDescriptor->application);
2053                     _node->addServer(this, _desc->application);
2054                 }
2055 
2056                 if(_node->getTraceLevels()->server > 0)
2057                 {
2058                     Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
2059                     out << "updated configuration for server `" << _id << "'";
2060                 }
2061             }
2062             else
2063             {
2064                 _node->addServer(this, _desc->application);
2065             }
2066 
2067             AdapterPrxDict adapters;
2068             for(ServerAdapterDict::const_iterator p = _adapters.begin(); p != _adapters.end(); ++p)
2069             {
2070                 adapters.insert(make_pair(p->first, p->second->getProxy()));
2071             }
2072             _load->finished(_this, adapters, _activationTimeout, _deactivationTimeout);
2073         }
2074         catch(const DeploymentException& ex)
2075         {
2076             //
2077             // Rollback old descriptor.
2078             //
2079             if(oldDescriptor)
2080             {
2081                 try
2082                 {
2083                     updateImpl(oldDescriptor);
2084                 }
2085                 catch(const Ice::Exception& e)
2086                 {
2087                     Ice::Warning out(_node->getTraceLevels()->logger);
2088                     out << "update failed:\n" << ex.reason << "\nand couldn't rollback old descriptor:\n" << e;
2089                 }
2090                 catch(const exception& e)
2091                 {
2092                     Ice::Warning out(_node->getTraceLevels()->logger);
2093                     out << "update failed:\n" << ex.reason << "\nand couldn't rollback old descriptor:\n" << e.what();
2094                 }
2095             }
2096             else if(!_destroy)
2097             {
2098                 _destroy = new DestroyCommand(this, true, true);
2099             }
2100 
2101             _load->failed(ex);
2102         }
2103 
2104         if(oldDescriptor && disabled != (_activation == Disabled))
2105         {
2106             _node->observerUpdateServer(getDynamicInfo());
2107         }
2108         setStateNoSync(Inactive);
2109         command = nextCommand();
2110     }
2111     if(command)
2112     {
2113         command->execute();
2114     }
2115 }
2116 
2117 void
updateImpl(const InternalServerDescriptorPtr & descriptor)2118 ServerI::updateImpl(const InternalServerDescriptorPtr& descriptor)
2119 {
2120     assert(_load && descriptor);
2121 
2122     _desc = descriptor;
2123     _waitForReplication = true;
2124 
2125     //
2126     // Remember if the server was just released by a session, this
2127     // will be used later to not update the configuration on the disk
2128     // (as an optimization and to allow users to review the
2129     // configuration file after allocating a server -- that's useful
2130     // if the server configuration is bogus and the session server
2131     // can't start).
2132     //
2133     bool serverSessionReleased = _desc && _desc->activation == "session" &&
2134         _desc->revision == descriptor->revision && !_desc->sessionId.empty() && descriptor->sessionId.empty();
2135 
2136     //
2137     // Go through the adapters and create the object adapter Ice
2138     // objects if necessary, also remove the old ones.
2139     //
2140     {
2141         ServerAdapterDict oldAdapters;
2142         oldAdapters.swap(_adapters);
2143         _serverLifetimeAdapters.clear();
2144         Ice::ObjectAdapterPtr adapter = _node->getAdapter();
2145         for(InternalAdapterDescriptorSeq::const_iterator r = _desc->adapters.begin(); r != _desc->adapters.end(); ++r)
2146         {
2147             try
2148             {
2149                 Ice::Identity id;
2150                 id.category = _this->ice_getIdentity().category + "Adapter";
2151                 id.name = _id + "-" + (*r)->id;
2152                 ServerAdapterIPtr servant = ServerAdapterIPtr::dynamicCast(adapter->find(id));
2153                 if(!servant)
2154                 {
2155                     AdapterPrx proxy = AdapterPrx::uncheckedCast(adapter->createProxy(id));
2156                     servant = new ServerAdapterI(_node, this, _id, proxy, (*r)->id, _activation != Disabled ||
2157                                                  _failureTime != IceUtil::Time());
2158                     adapter->add(servant, id);
2159                 }
2160                 _adapters.insert(make_pair((*r)->id, servant));
2161 
2162                 if((*r)->serverLifetime)
2163                 {
2164                     _serverLifetimeAdapters.insert((*r)->id);
2165                 }
2166             }
2167             catch(const Ice::ObjectAdapterDeactivatedException&)
2168             {
2169                 // IGNORE
2170             }
2171             catch(const Ice::LocalException& ex)
2172             {
2173                 Ice::Error out(_node->getTraceLevels()->logger);
2174                 out << "couldn't add adapter `" << (*r)->id << "':\n" << ex;
2175             }
2176             oldAdapters.erase((*r)->id);
2177         }
2178 
2179         //
2180         // Remove old object adapters.
2181         //
2182         for(ServerAdapterDict::const_iterator t = oldAdapters.begin(); t != oldAdapters.end(); ++t)
2183         {
2184             try
2185             {
2186                 t->second->destroy();
2187             }
2188             catch(const Ice::ObjectAdapterDeactivatedException&)
2189             {
2190                 // IGNORE
2191             }
2192             catch(const Ice::LocalException& ex)
2193             {
2194                 Ice::Error out(_node->getTraceLevels()->logger);
2195                 out << "couldn't destroy adapter `" << t->first << "':\n" << ex;
2196             }
2197         }
2198     }
2199 
2200     //
2201     // If the server was disabled because it failed (or because it's
2202     // the first time it's being updated). Set the activation mode
2203     // based on the descriptor activation. Otherwise, if the server is
2204     // disabled and failure time isn't set, we don't change the
2205     // activation since the user explicitely disabled the server.
2206     //
2207     if(_activation != Disabled || _failureTime != IceUtil::Time())
2208     {
2209         _activation = toServerActivation(_desc->activation);
2210         _failureTime = IceUtil::Time();
2211     }
2212 
2213     if(_timerTask)
2214     {
2215         _node->getTimer()->cancel(_timerTask);
2216         _timerTask = 0;
2217     }
2218 
2219     checkAndUpdateUser(_desc, true); // we pass true to update _uid/_gid.
2220 
2221     istringstream at(_desc->activationTimeout);
2222     if(!(at >> _activationTimeout) || !at.eof() || _activationTimeout == 0)
2223     {
2224         _activationTimeout = _waitTime;
2225     }
2226     istringstream dt(_desc->deactivationTimeout);
2227     if(!(dt >> _deactivationTimeout) || !dt.eof() || _deactivationTimeout == 0)
2228     {
2229         _deactivationTimeout = _waitTime;
2230     }
2231 
2232     //
2233     // Simplify the log paths and transform relative paths into
2234     // absolute paths, also make sure the logs are sorted.
2235     //
2236     for(Ice::StringSeq::const_iterator p = _desc->logs.begin(); p != _desc->logs.end(); ++p)
2237     {
2238         string path = IcePatch2Internal::simplify(*p);
2239         if(IceUtilInternal::isAbsolutePath(path))
2240         {
2241             _logs.push_back(path);
2242         }
2243         else
2244         {
2245             _logs.push_back(_node->getPlatformInfo().getCwd() + '/' + path);
2246         }
2247     }
2248     sort(_logs.begin(), _logs.begin());
2249 
2250     PropertyDescriptorSeqDict properties = getProperties(_desc);
2251     PropertyDescriptorSeq& props = properties["config"];
2252     _stdErrFile = getProperty(props, "Ice.StdErr");
2253     _stdOutFile = getProperty(props, "Ice.StdOut");
2254 
2255     //
2256     // If the server is a session server and it wasn't udpated but
2257     // just released by a session, we don't update the configuration,
2258     // it will be done when the server is re-allocated.
2259     //
2260     if(serverSessionReleased)
2261     {
2262         return;
2263     }
2264 
2265     //
2266     // Update the revision file.
2267     //
2268     updateRevision(_desc->uuid, _desc->revision);
2269 
2270     //
2271     // Create or update the server directories exists.
2272     //
2273     IcePatch2Internal::createDirectory(_serverDir);
2274     IcePatch2Internal::createDirectory(_serverDir + "/config");
2275     IcePatch2Internal::createDirectory(_serverDir + "/dbs");
2276     IcePatch2Internal::createDirectory(_serverDir + "/distrib");
2277     IcePatch2Internal::createDirectory(_serverDir + "/data");
2278 
2279     //
2280     // Create the configuration files, remove the old ones.
2281     //
2282     {
2283         //
2284         // We do not want to escape the properties if the Ice version is
2285         // previous to Ice 3.3.
2286         //
2287         Ice::StringSeq knownFiles;
2288         for(PropertyDescriptorSeqDict::const_iterator p = properties.begin(); p != properties.end(); ++p)
2289         {
2290             knownFiles.push_back(p->first);
2291 
2292             const string configFilePath = _serverDir + "/config/" + p->first;
2293             ofstream configfile(IceUtilInternal::streamFilename(configFilePath).c_str()); // configFilePath is a UTF-8 string
2294             if(!configfile.good())
2295             {
2296                 throw runtime_error("couldn't create configuration file: " + configFilePath);
2297             }
2298             configfile << "# Configuration file (" << IceUtil::Time::now().toDateTime() << ")" << endl << endl;
2299             for(PropertyDescriptorSeq::const_iterator r = p->second.begin(); r != p->second.end(); ++r)
2300             {
2301                 if(r->value.empty() && r->name.find('#') == 0)
2302                 {
2303                     configfile << r->name << endl;
2304                 }
2305                 else
2306                 {
2307                     configfile << r->name << "=" << r->value << endl;
2308                 }
2309             }
2310             configfile.close();
2311         }
2312         sort(knownFiles.begin(), knownFiles.end());
2313 
2314         //
2315         // Remove old configuration files.
2316         //
2317         Ice::StringSeq files = IcePatch2Internal::readDirectory(_serverDir + "/config");
2318         Ice::StringSeq toDel;
2319         set_difference(files.begin(), files.end(), knownFiles.begin(), knownFiles.end(), back_inserter(toDel));
2320         for(Ice::StringSeq::const_iterator q = toDel.begin(); q != toDel.end(); ++q)
2321         {
2322             if(q->find("config_") == 0)
2323             {
2324                 try
2325                 {
2326                     IcePatch2Internal::remove(_serverDir + "/config/" + *q);
2327                 }
2328                 catch(const exception& ex)
2329                 {
2330                     Ice::Warning out(_node->getTraceLevels()->logger);
2331                     out << "couldn't remove file `" << _serverDir << "/config/" << *q << "':\n" << ex.what();
2332                 }
2333             }
2334         }
2335     }
2336 
2337     //
2338     // Update the service data directories if necessary and remove the old ones.
2339     //
2340     if(_desc->services)
2341     {
2342         Ice::StringSeq knownDirs;
2343         for(Ice::StringSeq::const_iterator q = _desc->services->begin(); q != _desc->services->end(); ++q)
2344         {
2345             knownDirs.push_back("data_" + *q);
2346             IcePatch2Internal::createDirectory(_serverDir + "/data_" + *q);
2347         }
2348         sort(knownDirs.begin(), knownDirs.end());
2349 
2350         //
2351         // Remove old directories
2352         //
2353         Ice::StringSeq dirs = IcePatch2Internal::readDirectory(_serverDir);
2354         Ice::StringSeq svcDirs;
2355         for(Ice::StringSeq::const_iterator p = dirs.begin(); p != dirs.end(); ++p)
2356         {
2357             if(p->find("data_") == 0)
2358             {
2359                 svcDirs.push_back(*p);
2360             }
2361         }
2362         Ice::StringSeq toDel;
2363         set_difference(svcDirs.begin(), svcDirs.end(), knownDirs.begin(), knownDirs.end(), back_inserter(toDel));
2364         for(Ice::StringSeq::const_iterator p = toDel.begin(); p != toDel.end(); ++p)
2365         {
2366             try
2367             {
2368                 IcePatch2Internal::removeRecursive(_serverDir + "/" + *p);
2369             }
2370             catch(const exception& ex)
2371             {
2372                 Ice::Warning out(_node->getTraceLevels()->logger);
2373                 out << "couldn't remove directory `" << _serverDir << "/" << *p << "':\n" << ex.what();
2374             }
2375         }
2376     }
2377 
2378     //
2379     // Update the database environments if necessary and remove the
2380     // old ones.
2381     //
2382     {
2383         Ice::StringSeq knownDbEnvs;
2384         for(InternalDbEnvDescriptorSeq::const_iterator q = _desc->dbEnvs.begin(); q != _desc->dbEnvs.end(); ++q)
2385         {
2386             knownDbEnvs.push_back((*q)->name);
2387 
2388             string dbEnvHome = _serverDir + "/dbs/" + (*q)->name;
2389             IcePatch2Internal::createDirectory(dbEnvHome);
2390 
2391             if(!(*q)->properties.empty())
2392             {
2393                 string file = dbEnvHome + "/DB_CONFIG";
2394 
2395                 ofstream configfile(IceUtilInternal::streamFilename(file).c_str()); // file is a UTF-8 string
2396                 if(!configfile.good())
2397                 {
2398                     throw runtime_error("couldn't create configuration file `" + file + "'");
2399                 }
2400 
2401                 for(PropertyDescriptorSeq::const_iterator p = (*q)->properties.begin();
2402                     p != (*q)->properties.end(); ++p)
2403                 {
2404                     if(!p->name.empty())
2405                     {
2406                         configfile << p->name;
2407                         if(!p->value.empty())
2408                         {
2409                             configfile << " " << p->value;
2410                         }
2411                         configfile << endl;
2412                     }
2413                 }
2414                 configfile.close();
2415             }
2416         }
2417         sort(knownDbEnvs.begin(), knownDbEnvs.end());
2418 
2419         //
2420         // Remove old database environments.
2421         //
2422         Ice::StringSeq dbEnvs = IcePatch2Internal::readDirectory(_serverDir + "/dbs");
2423         Ice::StringSeq toDel;
2424         set_difference(dbEnvs.begin(), dbEnvs.end(), knownDbEnvs.begin(), knownDbEnvs.end(), back_inserter(toDel));
2425         for(Ice::StringSeq::const_iterator p = toDel.begin(); p != toDel.end(); ++p)
2426         {
2427             try
2428             {
2429                 IcePatch2Internal::removeRecursive(_serverDir + "/dbs/" + *p);
2430             }
2431             catch(const exception& ex)
2432             {
2433                 Ice::Warning out(_node->getTraceLevels()->logger);
2434                 out << "couldn't remove directory `" << _serverDir << "/dbs/" << *p << "':\n" << ex.what();
2435             }
2436         }
2437     }
2438 
2439 #ifndef _WIN32
2440     chownRecursive(_serverDir, _uid, _gid);
2441 #endif
2442 }
2443 
2444 void
checkRevision(const string & replicaName,const string & uuid,int revision) const2445 ServerI::checkRevision(const string& replicaName, const string& uuid, int revision) const
2446 {
2447     if(replicaName == "Master")
2448     {
2449         return;
2450     }
2451 
2452     string descUUID;
2453     int descRevision;
2454     if(_load)
2455     {
2456         descUUID = _load->getInternalServerDescriptor()->uuid;
2457         descRevision = _load->getInternalServerDescriptor()->revision;
2458     }
2459     else if(_desc)
2460     {
2461         descUUID = _desc->uuid;
2462         descRevision = _desc->revision;
2463     }
2464     else
2465     {
2466         string idFilePath = _serverDir + "/revision";
2467         ifstream is(IceUtilInternal::streamFilename(idFilePath).c_str()); // idFilePath is a UTF-8 string
2468         if(!is.good())
2469         {
2470             return;
2471         }
2472 
2473         char line[1024];
2474         is.getline(line, 1024); // Ignore comments
2475         is.getline(line, 1024);
2476         is.getline(line, 1024);
2477         string ignored;
2478         is >> ignored >> descUUID;
2479         is >> ignored >> descRevision;
2480     }
2481 
2482     if(uuid != descUUID)
2483     {
2484         throw DeploymentException("server from replica `" + replicaName + "' is from another application (`" + uuid +
2485                                   "')");
2486     }
2487     else if(revision != descRevision)
2488     {
2489         ostringstream os;
2490         os << "server from replica `" << replicaName << "' has a different version:\n"
2491            << "current revision: " << descRevision << "\nreplica revision: " << revision;
2492         throw DeploymentException(os.str());
2493     }
2494 }
2495 
2496 void
checkNoRestart(const InternalServerDescriptorPtr & desc)2497 ServerI::checkNoRestart(const InternalServerDescriptorPtr& desc)
2498 {
2499     assert(_desc);
2500 
2501     if(_desc->sessionId != desc->sessionId)
2502     {
2503         throw DeploymentException("server allocated by another session");
2504     }
2505 
2506     if(descriptorUpdated(_desc, desc, true)) // true = ignore properties
2507     {
2508         throw DeploymentException("update requires server to be stopped");
2509     }
2510 }
2511 
2512 #ifndef _WIN32
2513 void
checkAndUpdateUser(const InternalServerDescriptorPtr & desc,bool update)2514 ServerI::checkAndUpdateUser(const InternalServerDescriptorPtr& desc, bool update)
2515 #else
2516 void
2517 ServerI::checkAndUpdateUser(const InternalServerDescriptorPtr& desc, bool /*update*/)
2518 #endif
2519 {
2520 #ifndef _WIN32
2521     uid_t uid = getuid();
2522     uid_t gid = getgid();
2523 #endif
2524 
2525     //
2526     // Don't change the user if the server has the session activation
2527     // mode and if it's not currently owned by a session.
2528     //
2529     string user;
2530     if(desc->activation != "session" || !desc->sessionId.empty())
2531     {
2532         user = desc->user;
2533 #ifndef _WIN32
2534         //
2535         // Check if the node is running as root, if that's the case we
2536         // make sure that a user is set for the process.
2537         //
2538         if(uid == 0 && user.empty())
2539         {
2540             //
2541             // If no user is configured and if this server is owned by
2542             // a session we set the user to the session id, otherwise
2543             // we set it to "nobody".
2544             //
2545             user = !desc->sessionId.empty() ? desc->sessionId : "nobody";
2546         }
2547 #endif
2548     }
2549 
2550     if(!user.empty())
2551     {
2552         UserAccountMapperPrx mapper = _node->getUserAccountMapper();
2553         if(mapper)
2554         {
2555             try
2556             {
2557                 user = mapper->getUserAccount(user);
2558             }
2559             catch(const UserAccountNotFoundException&)
2560             {
2561                 throw runtime_error("couldn't find user account for user `" + user + "'");
2562             }
2563             catch(const Ice::LocalException& ex)
2564             {
2565                 ostringstream os;
2566                 os << "unexpected exception while trying to find user account for user `" << user << "':\n" << ex;
2567                 throw runtime_error(os.str());
2568             }
2569         }
2570 
2571 #ifdef _WIN32
2572         //
2573         // Windows doesn't support running processes under another
2574         // account (at least not easily, see the CreateProcessAsUser
2575         // documentation). So if a user is specified, we just check
2576         // that the node is running under the same user account as the
2577         // one which is specified.
2578         //
2579         vector<char> buf(256);
2580         buf.resize(256);
2581         DWORD size = static_cast<DWORD>(buf.size());
2582         bool success = GetUserName(&buf[0], &size);
2583         if(!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2584         {
2585             buf.resize(size);
2586             success = GetUserName(&buf[0], &size);
2587         }
2588         if(!success)
2589         {
2590             throw Ice::SyscallException(__FILE__, __LINE__, IceInternal::getSystemErrno());
2591         }
2592         if(user != string(&buf[0]))
2593         {
2594             throw runtime_error("couldn't load server under user account `" + user + "': feature not supported on Windows");
2595         }
2596     }
2597 #else
2598         //
2599         // Get the uid/gid associated with the given user.
2600         //
2601         struct passwd pwbuf;
2602         int sz = sysconf(_SC_GETPW_R_SIZE_MAX);
2603         if(sz == -1)
2604         {
2605             sz = 4096;
2606         }
2607         vector<char> buffer(sz);
2608         struct passwd *pw;
2609         int err = getpwnam_r(user.c_str(), &pwbuf, &buffer[0], buffer.size(), &pw);
2610         while(err == ERANGE && buffer.size() < 1024 * 1024) // Limit buffer to 1MB
2611         {
2612             buffer.resize(buffer.size() * 2);
2613             err = getpwnam_r(user.c_str(), &pwbuf, &buffer[0], buffer.size(), &pw);
2614         }
2615 
2616         if(err != 0)
2617         {
2618             throw Ice::SyscallException(__FILE__, __LINE__, err);
2619         }
2620         else if(pw == 0)
2621         {
2622             throw runtime_error("unknown user account `" + user + "'");
2623         }
2624 
2625         //
2626         // If the node isn't running as root and if the uid of the
2627         // configured user is different from the uid of the userr
2628         // running the node we throw, a regular user can't run a
2629         // process as another user.
2630         //
2631         if(uid != 0 && pw->pw_uid != uid)
2632         {
2633             throw runtime_error("node has insufficient privileges to load server under user account `" + user + "'");
2634         }
2635 
2636         if(pw->pw_uid == 0 &&
2637            _node->getCommunicator()->getProperties()->getPropertyAsInt("IceGrid.Node.AllowRunningServersAsRoot") <= 0)
2638         {
2639             throw runtime_error("running server as `root' is not allowed");
2640         }
2641 
2642         if(update)
2643         {
2644             _uid = pw->pw_uid;
2645             _gid = pw->pw_gid;
2646         }
2647     }
2648     else if(update)
2649     {
2650         _uid = uid;
2651         _gid = gid;
2652     }
2653 #endif
2654 }
2655 
2656 void
updateRevision(const string & uuid,int revision)2657 ServerI::updateRevision(const string& uuid, int revision)
2658 {
2659     _desc->uuid = uuid;
2660     _desc->revision = revision;
2661 
2662     if(_load)
2663     {
2664         _load->getInternalServerDescriptor()->uuid = uuid;
2665         _load->getInternalServerDescriptor()->revision = revision;
2666     }
2667 
2668     string idFilePath = _serverDir + "/revision";
2669     ofstream os(IceUtilInternal::streamFilename(idFilePath).c_str()); // idFilePath is a UTF-8 string
2670     if(os.good())
2671     {
2672         os << "#" << endl;
2673         os << "# This server belongs to the application `" << _desc->application << "'" << endl;
2674         os << "#" << endl;
2675         os << "uuid: " << _desc->uuid << endl;
2676         os << "revision: " << _desc->revision << endl;
2677     }
2678 }
2679 
2680 void
updateRuntimePropertiesCallback(const InternalServerDescriptorPtr & desc)2681 ServerI::updateRuntimePropertiesCallback(const InternalServerDescriptorPtr& desc)
2682 {
2683     Lock sync(*this);
2684     if(_state != Active || !_load)
2685     {
2686         return;
2687     }
2688 
2689     if(_load->finishRuntimePropertiesUpdate(desc, _process))
2690     {
2691         AdapterPrxDict adapters;
2692         for(ServerAdapterDict::const_iterator p = _adapters.begin(); p != _adapters.end(); ++p)
2693         {
2694             adapters.insert(make_pair(p->first, p->second->getProxy()));
2695         }
2696         _load->finished(_this, adapters, _activationTimeout, _deactivationTimeout);
2697     }
2698 }
2699 
2700 void
updateRuntimePropertiesCallback(const Ice::Exception & ex,const InternalServerDescriptorPtr & desc)2701 ServerI::updateRuntimePropertiesCallback(const Ice::Exception& ex, const InternalServerDescriptorPtr& desc)
2702 {
2703     Lock sync(*this);
2704     if(_state != Active || !_load)
2705     {
2706         return;
2707     }
2708 
2709     if(_load->finishRuntimePropertiesUpdate(desc, _process))
2710     {
2711         _load->failed(ex);
2712     }
2713 }
2714 
2715 bool
checkActivation()2716 ServerI::checkActivation()
2717 {
2718     //assert(locked());
2719     if(_state == ServerI::WaitForActivation || _state == ServerI::ActivationTimeout)
2720     {
2721         //
2722         // Mark the server as active if the server process proxy is registered (or it's not expecting
2723         // one to be registered) and if all the server lifetime adapters have been activated.
2724         //
2725         if((!_desc->processRegistered || _process) &&
2726            includes(_activatedAdapters.begin(), _activatedAdapters.end(),
2727                     _serverLifetimeAdapters.begin(), _serverLifetimeAdapters.end()))
2728         {
2729             setStateNoSync(ServerI::Active);
2730             return true;
2731         }
2732     }
2733     return false;
2734 }
2735 
2736 void
setState(InternalServerState st,const std::string & reason)2737 ServerI::setState(InternalServerState st, const std::string& reason)
2738 {
2739     ServerCommandPtr command;
2740     {
2741         Lock sync(*this);
2742         setStateNoSync(st, reason);
2743         command = nextCommand();
2744     }
2745     if(command)
2746     {
2747         command->execute();
2748     }
2749 }
2750 
2751 ServerCommandPtr
nextCommand()2752 ServerI::nextCommand()
2753 {
2754     ServerCommandPtr command;
2755     if(_stop && _stop->canExecute(_state))
2756     {
2757         command = _stop;
2758     }
2759     else if(_destroy && _destroy->canExecute(_state))
2760     {
2761         command = _destroy;
2762     }
2763     else if(_load && _load->canExecute(_state))
2764     {
2765         command = _load;
2766     }
2767     else if(_patch && _patch->canExecute(_state))
2768     {
2769         command = _patch;
2770     }
2771     else if(_start && _start->canExecute(_state))
2772     {
2773         command = _start;
2774     }
2775     if(command)
2776     {
2777         setStateNoSync(command->nextState());
2778     }
2779     return command;
2780 }
2781 
2782 void
setStateNoSync(InternalServerState st,const std::string & reason)2783 ServerI::setStateNoSync(InternalServerState st, const std::string& reason)
2784 {
2785     //
2786     // Ensure that the given state can be switched to.
2787     //
2788     switch(st)
2789     {
2790     case Inactive:
2791         break;
2792     case Patching:
2793         assert(_patch && _patch->canExecute(_state));
2794         break;
2795     case Loading:
2796         assert(_load && _load->canExecute(_state));
2797         break;
2798     case Activating:
2799         assert(_start && _start->canExecute(_state));
2800         break;
2801     case WaitForActivation:
2802         assert(_state == Activating);
2803         break;
2804     case ActivationTimeout:
2805         assert(_state == WaitForActivation);
2806         break;
2807     case Active:
2808         assert(_state == WaitForActivation || _state == ActivationTimeout);
2809         break;
2810     case Deactivating:
2811         //assert(_stop && _stop->canExecute(_state));
2812         break;
2813     case DeactivatingWaitForProcess:
2814         assert(_state == Deactivating);
2815         break;
2816     case Destroying:
2817         assert(_state == Inactive && _destroy && _destroy->canExecute(_state));
2818         break;
2819     case Destroyed:
2820         assert(_destroy);
2821         break;
2822     }
2823 
2824     //
2825     // Change the current state.
2826     //
2827     InternalServerState previous = _state;
2828     _state = st;
2829 
2830     //
2831     // Check if some commands are done.
2832     //
2833     bool loadFailure = false;
2834     switch(_state)
2835     {
2836     case Inactive:
2837         if(previous == Loading)
2838         {
2839             _load = 0;
2840         }
2841         if(previous == Patching)
2842         {
2843             _patch = 0;
2844         }
2845         if(_stop)
2846         {
2847             _stop->finished();
2848             _stop = 0;
2849         }
2850         break;
2851     case Active:
2852         if(_start)
2853         {
2854             _start->finished();
2855             _start = 0;
2856         }
2857         break;
2858     case ActivationTimeout:
2859         if(_start)
2860         {
2861             _start->failed(reason);
2862             _start = 0;
2863         }
2864         break;
2865     case Deactivating:
2866         if(_start)
2867         {
2868             _start->failed(reason.empty() ? string("The server is being deactivated.") : reason);
2869             _start = 0;
2870         }
2871         break;
2872     case Destroying:
2873         loadFailure = _destroy->loadFailure();
2874         if(_patch)
2875         {
2876             _patch->destroyed();
2877             _patch = 0;
2878         }
2879         if(_load)
2880         {
2881             _load->failed(DeploymentException("The server is being destroyed."));
2882             _load = 0;
2883         }
2884         if(_start)
2885         {
2886             _start->failed("The server is being destroyed.");
2887             _start = 0;
2888         }
2889         if(_stop)
2890         {
2891             _stop->failed("The server is being destroyed.");
2892             _stop = 0;
2893         }
2894         break;
2895     case Destroyed:
2896         if(_destroy)
2897         {
2898             loadFailure = _destroy->loadFailure();
2899             _destroy->finished();
2900             _destroy = 0;
2901         }
2902         notifyAll(); // for getProperties()
2903         break;
2904     default:
2905         break;
2906     }
2907 
2908     if(_timerTask)
2909     {
2910         _node->getTimer()->cancel(_timerTask);
2911         _timerTask = 0;
2912     }
2913 
2914     if(_state == Destroyed && !_load)
2915     {
2916         //
2917         // If the server is destroyed and there's no load command, we
2918         // remove the servant from the ASM.
2919         //
2920         try
2921         {
2922             _node->getAdapter()->remove(_this->ice_getIdentity());
2923         }
2924         catch(const Ice::ObjectAdapterDeactivatedException&)
2925         {
2926             // IGNORE
2927         }
2928         _desc = 0;
2929     }
2930     else if(_state == Inactive)
2931     {
2932         if(_activation == Always)
2933         {
2934             assert(!_timerTask);
2935             _timerTask = new DelayedStart(this, _node->getTraceLevels());
2936             try
2937             {
2938                 _node->getTimer()->schedule(_timerTask, IceUtil::Time::milliSeconds(500));
2939             }
2940             catch(const IceUtil::Exception&)
2941             {
2942                 // Ignore, timer is destroyed because node is shutting down.
2943             }
2944         }
2945         else if(_activation == Disabled && _disableOnFailure > 0 && _failureTime != IceUtil::Time())
2946         {
2947             //
2948             // If the server was disabled because it failed, we
2949             // schedule a callback to re-enable it. We add 500ms to
2950             // the disable on failure duration to make sure that the
2951             // server will be ready to be reactivated when the
2952             // callback is executed.
2953             //
2954             assert(!_timerTask);
2955             _timerTask = new DelayedStart(this, _node->getTraceLevels());
2956             try
2957             {
2958                 IceUtil::Time now = IceUtil::Time::now(IceUtil::Time::Monotonic);
2959                 if(now - _failureTime < IceUtil::Time::seconds(_disableOnFailure))
2960                 {
2961                     _node->getTimer()->schedule(_timerTask,
2962                                                 IceUtil::Time::seconds(_disableOnFailure) - now + _failureTime +
2963                                                 IceUtil::Time::milliSeconds(500));
2964                 }
2965                 else
2966                 {
2967                     _node->getTimer()->schedule(_timerTask, IceUtil::Time::milliSeconds(500));
2968                 }
2969             }
2970             catch(const IceUtil::Exception&)
2971             {
2972                 // Ignore, timer is destroyed because node is shutting down.
2973             }
2974         }
2975     }
2976     else if(_state == Active && _load)
2977     {
2978         //
2979         // If there's a pending load command, it's time to update the
2980         // runtime properties of the server now that it's active.
2981         //
2982         _load->startRuntimePropertiesUpdate(_process);
2983     }
2984 
2985     //
2986     // Don't send the server update if the state didn't change or if
2987     // the server couldn't be forked. If the server is destroyed, we
2988     // also check if it's the result of a load failure. If that's the
2989     // case we don't send an update because the server was never
2990     // actually loaded.
2991     //
2992     if(toServerState(previous) != toServerState(_state) &&
2993        !(previous == Inactive && _state == Deactivating) &&
2994        !loadFailure)
2995     {
2996         _node->observerUpdateServer(getDynamicInfo());
2997     }
2998 
2999     if(_node->getTraceLevels()->server > 1)
3000     {
3001         if(_state == ServerI::Active)
3002         {
3003             Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3004             out << "changed server `" << _id << "' state to `Active'";
3005         }
3006         else if(_state == ServerI::Inactive)
3007         {
3008             if(_node->getTraceLevels()->server != 2 && !(previous == ServerI::Loading || previous == ServerI::Patching))
3009             {
3010                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3011                 out << "changed server `" << _id << "' state to `Inactive'";
3012             }
3013         }
3014         else if(_state == ServerI::Destroyed)
3015         {
3016             Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3017             out << "changed server `" << _id << "' state to `Destroyed'";
3018         }
3019         else if(_node->getTraceLevels()->server > 2)
3020         {
3021             if(_state == ServerI::WaitForActivation)
3022             {
3023                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3024                 out << "changed server `" << _id << "' state to `WaitForActivation'";
3025             }
3026             else if(_state == ServerI::ActivationTimeout)
3027             {
3028                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3029                 out << "changed server `" << _id << "' state to `ActivationTimeout'";
3030             }
3031             else if(_state == ServerI::Activating)
3032             {
3033                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3034                 out << "changed server `" << _id << "' state to `Activating'";
3035             }
3036             else if(_state == ServerI::Deactivating)
3037             {
3038                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3039                 out << "changed server `" << _id << "' state to `Deactivating'";
3040             }
3041             else if(_state == ServerI::DeactivatingWaitForProcess)
3042             {
3043                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3044                 out << "changed server `" << _id << "' state to `DeactivatingWaitForProcess'";
3045             }
3046             else if(_state == ServerI::Destroying)
3047             {
3048                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3049                 out << "changed server `" << _id << "' state to `Destroying'";
3050             }
3051             else if(_state == ServerI::Loading)
3052             {
3053                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3054                 out << "changed server `" << _id << "' state to `Loading'";
3055             }
3056             else if(_state == ServerI::Patching)
3057             {
3058                 Ice::Trace out(_node->getTraceLevels()->logger, _node->getTraceLevels()->serverCat);
3059                 out << "changed server `" << _id << "' state to `Loading'";
3060             }
3061         }
3062     }
3063 }
3064 
3065 ServerState
toServerState(InternalServerState st) const3066 ServerI::toServerState(InternalServerState st) const
3067 {
3068     switch(st)
3069     {
3070     case ServerI::Inactive:
3071     case ServerI::Activating:
3072     case ServerI::Patching:
3073     case ServerI::Loading:
3074         return IceGrid::Inactive;
3075     case ServerI::WaitForActivation:
3076         return IceGrid::Activating;
3077     case ServerI::ActivationTimeout:
3078         return IceGrid::ActivationTimedOut;
3079     case ServerI::Active:
3080         return IceGrid::Active;
3081     case ServerI::Deactivating:
3082     case ServerI::DeactivatingWaitForProcess:
3083         return IceGrid::Deactivating;
3084     case ServerI::Destroying:
3085         return IceGrid::Destroying;
3086     case ServerI::Destroyed:
3087         return IceGrid::Destroyed;
3088     default:
3089         assert(false);
3090         return IceGrid::Destroyed;
3091     }
3092 }
3093 
3094 ServerI::ServerActivation
toServerActivation(const string & activation) const3095 ServerI::toServerActivation(const string& activation) const
3096 {
3097     if(activation == "on-demand")
3098     {
3099         return OnDemand;
3100     }
3101     else if(activation == "session")
3102     {
3103         return Session;
3104     }
3105     else if(activation == "always")
3106     {
3107         return Always;
3108     }
3109     else if(activation == "manual" || activation.empty())
3110     {
3111         return Manual;
3112     }
3113     else
3114     {
3115         Ice::Warning out(_node->getTraceLevels()->logger);
3116         out << "unknown activation mode `" << activation << "' for server `" << _id << "'";
3117         return Manual;
3118     }
3119 }
3120 
3121 ServerDynamicInfo
getDynamicInfo() const3122 ServerI::getDynamicInfo() const
3123 {
3124     ServerDynamicInfo descriptor;
3125     descriptor.id = _id;
3126     descriptor.state = toServerState(_state);
3127 
3128     //
3129     // NOTE: this must be done only for the active state. Otherwise, we could get a
3130     // deadlock since getPid() will lock the activator and since this method might
3131     // be called from the activator locked.
3132     //
3133     descriptor.pid = _pid;
3134     descriptor.enabled = _activation != Disabled;
3135     return descriptor;
3136 }
3137 
3138 string
getFilePath(const string & filename) const3139 ServerI::getFilePath(const string& filename) const
3140 {
3141     if(filename == "stderr")
3142     {
3143         if(_stdErrFile.empty())
3144         {
3145             throw FileNotAvailableException("Ice.StdErr configuration property is not set");
3146         }
3147         return _stdErrFile;
3148     }
3149     else if(filename == "stdout")
3150     {
3151         if(_stdOutFile.empty())
3152         {
3153             throw FileNotAvailableException("Ice.StdOut configuration property is not set");
3154         }
3155         return _stdOutFile;
3156     }
3157     else if(!filename.empty() && filename[0] == '#')
3158     {
3159         string path = IcePatch2Internal::simplify(filename.substr(1));
3160         if(!IceUtilInternal::isAbsolutePath(path))
3161         {
3162             path = _node->getPlatformInfo().getCwd() + "/" + path;
3163         }
3164         if(find(_logs.begin(), _logs.end(), path) == _logs.end())
3165         {
3166             throw FileNotAvailableException("unknown log file `" + path + "'");
3167         }
3168         return path;
3169     }
3170     else
3171     {
3172         throw FileNotAvailableException("unknown file");
3173     }
3174 }
3175 
3176 PropertyDescriptorSeqDict
getProperties(const InternalServerDescriptorPtr & desc)3177 ServerI::getProperties(const InternalServerDescriptorPtr& desc)
3178 {
3179     //
3180     // Copy the descriptor properties.
3181     //
3182     PropertyDescriptorSeqDict propDict = desc->properties;
3183     PropertyDescriptorSeq& props = propDict["config"];
3184 
3185     //
3186     // Cache the path of the stderr/stdout file, first check if the
3187     // node OutputDir property is set and then we check the server
3188     // configuration file for the Ice.StdErr and Ice.StdOut
3189     // properties.
3190     //
3191     string stdErrFile = getProperty(props, "Ice.StdErr");
3192     string stdOutFile = getProperty(props, "Ice.StdOut");
3193     string outputDir = _node->getOutputDir();
3194     if(!outputDir.empty())
3195     {
3196         if(stdErrFile.empty())
3197         {
3198             stdErrFile = outputDir + "/" + _id + (_node->getRedirectErrToOut() ? ".out" : ".err");
3199             props.push_back(createProperty("Ice.StdErr", stdErrFile));
3200         }
3201         if(stdOutFile.empty())
3202         {
3203             stdOutFile = outputDir + "/" + _id + ".out";
3204             props.push_back(createProperty("Ice.StdOut", stdOutFile));
3205         }
3206     }
3207 
3208     //
3209     // Add the locator proxy property and the node properties override
3210     //
3211     {
3212         const PropertyDescriptorSeq& overrides = _node->getPropertiesOverride();
3213         for(PropertyDescriptorSeqDict::iterator p = propDict.begin(); p != propDict.end(); ++p)
3214         {
3215             if(getProperty(p->second, "Ice.Default.Locator").empty())
3216             {
3217                 Ice::PropertiesPtr properties = _node->getCommunicator()->getProperties();
3218 
3219                 string locator = properties->getProperty("Ice.Default.Locator");
3220                 if(!locator.empty())
3221                 {
3222                     p->second.push_back(createProperty("Ice.Default.Locator", locator));
3223                 }
3224 
3225                 string discoveryPlugin = properties->getProperty("Ice.Plugin.IceLocatorDiscovery");
3226                 if(!discoveryPlugin.empty())
3227                 {
3228                     p->second.push_back(createProperty("Ice.Plugin.IceLocatorDiscovery", discoveryPlugin));
3229                     p->second.push_back(createProperty("IceLocatorDiscovery.InstanceName", _node->getInstanceName()));
3230                 }
3231             }
3232 
3233             if(!overrides.empty())
3234             {
3235                 p->second.push_back(createProperty("# Node properties override"));
3236                 p->second.insert(p->second.end(), overrides.begin(), overrides.end());
3237             }
3238         }
3239     }
3240 
3241     return propDict;
3242 }
3243