Passenger: LoggingServer.h Source File

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

# LoggingServer.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (c) 2010 Phusion
    00004  *
    00005  *  "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  Permission is hereby granted, free of charge, to any person obtaining a copy
    00008  *  of this software and associated documentation files (the "Software"), to deal
    00009  *  in the Software without restriction, including without limitation the rights
    00010  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00011  *  copies of the Software, and to permit persons to whom the Software is
    00012  *  furnished to do so, subject to the following conditions:
    00013  *
    00014  *  The above copyright notice and this permission notice shall be included in
    00015  *  all copies or substantial portions of the Software.
    00016  *
    00017  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00018  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00019  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00020  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00021  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00022  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00023  *  THE SOFTWARE.
    00024  */
    00025 #ifndef _PASSENGER_LOGGING_SERVER_H_
    00026 #define _PASSENGER_LOGGING_SERVER_H_
    00027
    00028 #include <oxt/system_calls.hpp>
    00029
    00030 #include <string>
    00031 #include <vector>
    00032
    00033 #include <sys/types.h>
    00034 #include <sys/stat.h>
    00035 #include <cstdio>
    00036 #include <cstdlib>
    00037 #include <cstring>
    00038 #include <grp.h>
    00039
    00040 #include "MessageServer.h"
    00041 #include "Logging.h"
    00042 #include "SystemTime.h"
    00043 #include "Exceptions.h"
    00044 #include "FileDescriptor.h"
    00045 #include "Utils.h"
    00046
    00047 namespace Passenger {
    00048
    00049 using namespace std;
    00050 using namespace oxt;
    00051
    00052 class LoggingServer: public MessageServer::Handler {
    00053 private:
    00054         string dir;
    00055         string dirPermissions;
    00056         mode_t filePermissions;
    00057         gid_t gid;
    00058
    00059 public:
    00060         LoggingServer(const string &dir, const string &permissions = "u=rwx,g=rx,o=rx", gid_t gid = GROUP_NOT_GIVEN) {
    00061                 this->dir = dir;
    00062                 this->gid = gid;
    00063                 dirPermissions = permissions;
    00064                 filePermissions = parseModeString(permissions) & ~(S_IXUSR | S_IXGRP | S_IXOTH);
    00065         }
    00066
    00067         virtual bool processMessage(MessageServer::CommonClientContext &commonContext,
    00068                                     MessageServer::ClientContextPtr &handlerSpecificContext,
    00069                                     const vector<string> &args)
    00070         {
    00071                 if (args[0] == "open log file") {
    00072                         string groupName = args[1];
    00073                         unsigned long long timestamp = atoll(args[2].c_str());
    00074                         string category = args[3];
    00075
    00076                         if (timestamp > SystemTime::getUsec()) {
    00077                                 commonContext.channel.write("error",
    00078                                         "Timestamp may not be in the future", NULL);
    00079                                 return true;
    00080                         }
    00081
    00082                         string groupDir;
    00083                         string filename;
    00084                         try {
    00085                                 groupDir = TxnLogger::determineGroupDir(dir, groupName);
    00086                                 filename = TxnLogger::determineLogFilename(dir,
    00087                                         groupName, category, timestamp);
    00088                         } catch (const ArgumentException &e) {
    00089                                 commonContext.channel.write("error", e.what(), NULL);
    00090                                 return true;
    00091                         }
    00092
    00093                         FileDescriptor fd;
    00094                         int ret;
    00095
    00096                         try {
    00097                                 makeDirTree(extractDirName(filename), dirPermissions,
    00098                                         USER_NOT_GIVEN, gid);
    00099                         } catch (const FileSystemException &e) {
    00100                                 commonContext.channel.write("error", e.what(), NULL);
    00101                                 return true;
    00102                         }
    00103
    00104                         try {
    00105                                 createFile(groupDir + "/group_name.txt", groupName,
    00106                                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
    00107                                         USER_NOT_GIVEN, GROUP_NOT_GIVEN,
    00108                                         false);
    00109                         } catch (const FileSystemException &e) {
    00110                                 commonContext.channel.write("error", e.what(), NULL);
    00111                                 return true;
    00112                         }
    00113
    00114                         fd = syscalls::open(filename.c_str(),
    00115                                 O_CREAT | O_WRONLY | O_APPEND,
    00116                                 filePermissions);
    00117                         if (fd == -1) {
    00118                                 const char *message = strerror(errno);
    00119                                 commonContext.channel.write("error", message, NULL);
    00120                                 return true;
    00121                         }
    00122
    00123                         do {
    00124                                 ret = fchmod(fd, filePermissions);
    00125                         } while (ret == -1 && errno == EINTR);
    00126                         commonContext.channel.write("ok", NULL);
    00127                         commonContext.channel.writeFileDescriptor(fd);
    00128                         return true;
    00129                 } else {
    00130                         return false;
    00131                 }
    00132         }
    00133 };
    00134
    00135 } // namespace Passenger
    00136
    00137 #endif /* _PASSENGER_LOGGING_SERVER_H_ */