📄 log.cc
字号:
// -*- Mode: C++; -*-// Package : omniNames// log.cc Author : Tristan Richardson (tjr)//// Copyright (C) 1997-1999 AT&T Laboratories Cambridge//// This file is part of omniNames.//// omniNames is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,// USA.//#include <string.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <time.h>#include <fcntl.h>#if defined(__VMS) && __VMS_VER < 70000000# include <omniVMS/unlink.hxx># include <omniVms/utsname.hxx>#endif#include <NamingContext_i.h>#include <ObjectBinding.h>#include <INSMapper.h>#include <log.h>#ifdef HAVE_STD# include <iostream># include <iomanip> using namespace std;#else# include <iostream.h># include <iomanip.h>#endif#ifdef __WIN32__# include <io.h># include <winbase.h># define stat(x,y) _stat(x,y)# define unlink(x) _unlink(x)#else# include <unistd.h># include <sys/utsname.h>#endif#if defined(__nextstep__)# include <libc.h># include <sys/param.h>#endif#ifndef O_SYNC# ifdef O_FSYNC // FreeBSD 3.2 does not have O_SYNC???# define O_SYNC O_FSYNC# endif#endif#ifdef HAVE_STD# define USE_STREAM_OPEN# define OPEN(name,mode,perm) open(name,mode)#elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x500# define USE_STREAM_OPEN# define OPEN(name,mode,perm) open(name,mode,perm)#elif defined(__DMC__)# define USE_STREAM_OPEN# define OPEN(name,mode,perm) open(name,mode,perm)#elif defined(__ICC)# define USE_STREAM_OPEN# define OPEN(name,mode,perm) open(name,mode,perm)#endif#ifndef HAVE_STRDUP// we have no strdupstatic char *strdup (char* str){ char *newstr; newstr = (char *) malloc (strlen (str) + 1); if (newstr) strcpy (newstr, str); return newstr;}#endif // not HAVE_STRDUPstaticinline void reallyFlush(ofstream& f) { f.flush();#ifdef needsExplicitFsync ::fsync(f.rdbuf()->fd());#endif}extern void usage();//// This class can be used to generate timestamps. The t() method normally// returns a timestamp string, but if the same timestamp (to the nearest// second) would be returned as last time then an empty string is returned// instead.//class timestamp { char str[29];public: timestamp(void) { str[0] = '\n'; str[1] = str[28] = '\0'; } char* t(void) { time_t t = time(NULL); char *p = ctime(&t); if (strncmp(p, &str[1], 24) == 0) { return &str[28]; } strncpy(&str[1], p, 24); str[25] = ':'; str[26] = '\n'; str[27] = '\n'; return str; }};timestamp ts;//// Constructor for class omniNameslog. There will normally be only one// instance of this class. Unfortunately the initialisation of the class// cannot be completed in the constructor - the rest is done in the init()// member function. This is because the main program cannot give us// pointers to the ORB and the BOA until it has worked out which port to// listen on, but it normally finds out the port from the log file. So in// this constructor we initialise as much as we can, find out the port from// the log file if there is one and return. Then the main program// initialises the ORB and the BOA and calls init().//omniNameslog::omniNameslog(int& p,char* logdir) : port(p){ startingUp = 1; checkpointNeeded = 1; line = 1;#ifdef __WIN32__ struct _stat sb;#else struct stat sb;#endif if (!logdir && (logdir = getenv(LOGDIR_ENV_VAR)) == NULL) logdir = strdup(DEFAULT_LOGDIR);#if !defined(__WIN32__) && !defined(__VMS) if (logdir[0] != '/') { cerr << ts.t() << "Error: " << LOGDIR_ENV_VAR << " (" << logdir << ") is not an absolute path name." << endl; exit(1); } if (logdir[strlen(logdir)-1] == '/') { logdir[strlen(logdir)-1] = '\0'; // strip trailing '/' }#ifdef HAVE_UNAME struct utsname un; if (uname(&un) < 0) { cerr << ts.t() << "Error: cannot get the name of this host." << endl; exit(1); } char* logname = new char[strlen(logdir) + strlen("/omninames-") + strlen(un.nodename) + 1]; sprintf(logname, "%s/omninames-%s", logdir, un.nodename);#elif HAVE_GETHOSTNAME // Apparently on some AIX versions, MAXHOSTNAMELEN is too small (32) to // reflect the true size a hostname can be. Check and fix the value.#ifndef MAXHOSTNAMELEN# define MAXHOSTNAMELEN 256#elif MAXHOSTNAMELEN < 64# undef MAXHOSTNAMELEN# define MAXHOSTNAMELEN 256#endif char hostname[MAXHOSTNAMELEN+1]; if (gethostname(hostname, MAXHOSTNAMELEN) < 0) { cerr << ts.t() << "Error: cannot get the name of this host." << endl; exit(1); } char* logname = new char[strlen(logdir) + strlen("/omninames-") + strlen(hostname) + 1]; sprintf(logname, "%s/omninames-%s", logdir, hostname);#endif // HAVE_UNAME#elif defined(__WIN32__) // Get host name: DWORD machineName_len = MAX_COMPUTERNAME_LENGTH+1; char* machineName = new char[machineName_len]; if (!GetComputerName((LPTSTR) machineName, &machineName_len)) { cerr << ts.t() << "Error: cannot get the name of this host." << endl; exit(1); } char* logname = new char[strlen(logdir) + strlen("\\omninames-") + strlen(machineName) + 1]; sprintf(logname, "%s\\omninames-%s", logdir, machineName); delete[] machineName;#else // VMS char last( logdir[strlen(logdir)-1] ); if (last != ':' && last != ']') { cerr << ts.t() << "Error: " << LOGDIR_ENV_VAR << " (" << logdir << ") is not a directory name." << endl; exit(1); }// if (logdir[strlen(logdir)-1] == '/') {// logdir[strlen(logdir)-1] = '\0'; // strip trailing '/'// } struct utsname un; if (uname(&un) < 0) { cerr << ts.t() << "Error: cannot get the name of this host." << endl; exit(1); } char* logname = new char[strlen(logdir) + strlen("/omninames-") + strlen(un.nodename) + 1]; sprintf(logname, "%somninames-%s", logdir, un.nodename);#endif#ifndef __VMS active = new char[strlen(logname)+strlen(".log")+1]; sprintf(active,"%s.log",logname); backup = new char[strlen(logname)+strlen(".bak")+1]; sprintf(backup,"%s.bak",logname); checkpt = new char[strlen(logname)+strlen(".ckp")+1]; sprintf(checkpt,"%s.ckp",logname);#else // specify latest version: active = new char[strlen(logname)+strlen(".log;")+1]; sprintf(active,"%s.log;",logname); backup = new char[strlen(logname)+strlen(".bak;")+1]; sprintf(backup,"%s.bak;",logname); checkpt = new char[strlen(logname)+strlen(".ckp;")+1]; sprintf(checkpt,"%s.ckp;",logname);#endif delete [] logname; if (port != 0) { // // Starting for the first time - make sure log file doesn't exist, and // for safety, that there is no backup file either. // firstTime = 1; if (stat(active,&sb) == 0) { cerr << ts.t() << "Error: log file '" << active << "' exists. Can't use -start option." << endl; exit(1); } if (stat(backup,&sb) == 0) { cerr << ts.t() << "Error: backup file '" << backup << "' exists. Can't use -start option." << endl; exit(1); } } else { // // Restart - get port info from log file. // firstTime = 0;#ifdef __WIN32__ ifstream initf(active,ios::in);#else ifstream initf(active);#endif if (!initf) { cerr << ts.t() << "Error: cannot open log file '" << active << "'." << endl; if (stat(backup,&sb) == 0) { cerr << "Info: backup file '" << backup << "' exists." << endl << "This must be removed if you want to use the -start option." << endl; } usage(); } try { getPort(initf); } catch (IOError&) { cerr << ts.t() << "Error: reading log file '" << active << "' failed: " << flush; perror(""); initf.close(); exit(1); } catch (ParseError&) { cerr << ts.t() << "Error: parse error in log file '" << active << "' at line " << line << "." << endl; initf.close(); exit(1); } p = port; initf.close(); }}voidomniNameslog::init(CORBA::ORB_ptr the_orb, PortableServer::POA_ptr the_poa, PortableServer::POA_ptr the_ins_poa){ orb = the_orb; poa = the_poa; ins_poa = the_ins_poa; if (firstTime) { // // starting for the first time - create an initial log file with the // port specification and the root context. // cerr << ts.t() << "Starting omniNames for the first time." << endl; try {#ifdef USE_STREAM_OPEN logf.OPEN(active,ios::out|ios::trunc,0666); if (!logf) throw IOError();#else# ifdef __WIN32__ int fd = _open(active, O_WRONLY | O_CREAT | O_TRUNC, _S_IWRITE);# else int fd = open(active, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0666);# endif if (fd < 0) throw IOError(); logf.attach(fd);#endif putPort(port, logf); reallyFlush(logf); { PortableServer::ObjectId_var refid = PortableServer::string_to_ObjectId("NameService"); putCreate(refid, logf); } logf.close(); if (!logf) throw IOError();// a bug in sparcworks C++ means that the fd doesn't get closed.#if defined(__sunos__) && defined(__SUNPRO_CC) && __SUNPRO_CC < 0x500 if (close(fd) < 0) throw IOError();#endif } catch (IOError& ex) { cerr << ts.t() << "Error: cannot create initial log file '" << active << "': " << endl; perror(""); cerr << "\nYou can set the environment variable " << LOGDIR_ENV_VAR << " to specify the\ndirectory where the log files are kept.\n" << endl; logf.close(); unlink(active); exit(1); } cerr << ts.t() << "Wrote initial log file." << endl; } // claim the global lock as a writer (ie exclusive). NamingContext_i::lock.writerIn(); ifstream initf(active); if (!initf) { cerr << ts.t() << "Error: cannot open log file '" << active << "'." << endl; exit(1); } try { line = 1; while (initf && (initf.peek() != EOF)) { char* cmd; getNonfinalString(cmd, initf); if (strcmp(cmd, "port") == 0) { while (initf && (initf.get() != '\n')); // ignore rest of line line++; } else if (strcmp(cmd, "create") == 0) { getCreate(initf); } else if (strcmp(cmd, "destroy") == 0) { getDestroy(initf); } else if (strcmp(cmd, "bind") == 0) { getBind(initf); } else if (strcmp(cmd, "unbind") == 0) { getUnbind(initf); } else { cerr << ts.t() << "Error: unknown command '" << cmd << "' in log file '" << active << "'." << endl; throw ParseError(); } delete [] cmd; } initf.close(); } catch (IOError&) { cerr << ts.t() << "Error: reading log file '" << active << "' failed: " << flush; perror(""); initf.close(); exit(1); } catch (ParseError&) { cerr << ts.t() << "Error: parse error in log file '" << active << "' at line " << line << "." << endl; initf.close(); exit(1); } cerr << ts.t() << "Read log file successfully." << endl; CosNaming::NamingContext_ptr rootContext = NamingContext_i::headContext->_this(); { // Check to see if we need an INS forwarding agent omniIOR_var ior; ior = rootContext->_getIOR(); IIOP::ProfileBody iiop; const IOP::TaggedProfileList& profiles = ior->iopProfiles(); for (CORBA::ULong index = 0; index < profiles.length(); index++) { if (profiles[index].tag == IOP::TAG_INTERNET_IOP) { IIOP::unmarshalProfile(profiles[index],iiop); break; } } if (strncmp((const char*)iiop.object_key.get_buffer(), "NameService", 11)) { cerr << ts.t() << "(Pre-INS log file)" << endl; new INSMapper(the_ins_poa, rootContext); } } char* p = orb->object_to_string(rootContext); cerr << ts.t() << "Root context is " << p << endl; // Now use the backdoor to tell the bootstrap agent in this // address space to return this root context in response to // CORBA::InitialReferences::get("NameService"); _omni_set_NameService(rootContext); delete p; CORBA::release(rootContext); // dispose of the object reference#ifdef USE_STREAM_OPEN logf.OPEN(active,ios::out|ios::app,0666); if (!logf) { cerr << ts.t() << "Error: cannot open log file '" << active << "' for writing." << endl; exit(1); }#else# ifdef __WIN32__ int fd = _open(active, O_WRONLY | O_APPEND);# else int fd = open(active, O_WRONLY | O_APPEND | O_SYNC);# endif if (fd < 0) { cerr << ts.t() << "Error: cannot open log file '" << active << "' for writing." << endl; exit(1); } logf.attach(fd);#endif startingUp = 0; NamingContext_i::lock.writerOut(); // remove checkpoint. This will protect us from trouble if the previous // incarnation crashed during checkpointing and at the // time when both active and checkpoint are linked to the same file. unlink(checkpt);}voidomniNameslog::create(const PortableServer::ObjectId& id){ if (!startingUp) { try { putCreate(id, logf); reallyFlush(logf); } catch (IOError& ex) { cerr << ts.t() << flush; perror("I/O error writing log file"); logf.clear(); throw CORBA::PERSIST_STORE(); } checkpointNeeded = 1; }}voidomniNameslog::destroy(CosNaming::NamingContext_ptr nc){ if (!startingUp) { try { putDestroy(nc, logf); reallyFlush(logf); } catch (IOError& ex) { cerr << ts.t() << flush; perror("I/O error writing log file"); logf.clear(); throw CORBA::PERSIST_STORE(); } checkpointNeeded = 1; }}voidomniNameslog::bind(CosNaming::NamingContext_ptr nc, const CosNaming::Name& n, CORBA::Object_ptr obj, CosNaming::BindingType t){ if (!startingUp) { try { putBind(nc, n, obj, t, logf); reallyFlush(logf); } catch (IOError& ex) { cerr << ts.t() << flush; perror("I/O error writing log file"); logf.clear(); throw CORBA::PERSIST_STORE(); } checkpointNeeded = 1; }}voidomniNameslog::unbind(CosNaming::NamingContext_ptr nc, const CosNaming::Name& n){ if (!startingUp) { try { putUnbind(nc, n, logf); reallyFlush(logf); } catch (IOError& ex) { cerr << ts.t() << flush; perror("I/O error writing log file"); logf.clear();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -