37 #include <sys/types.h>    40 # include <sys/wait.h>    53 split_words(
const string &text, vector<string> &words, 
char ws = 
' ')
    56     if (i < text.length() && text[0] == ws) {
    57         i = text.find_first_not_of(ws, i);
    59     while (i < text.length()) {
    60         size_t j = text.find_first_of(ws, i);
    61         words.push_back(text.substr(i, j - i));
    62         i = text.find_first_not_of(ws, j);
    68                        double timeout_, 
bool writable, 
int flags)
    70                          timeout_, get_progcontext(progname, args), writable,
    73     LOGCALL_CTOR(DB, 
"ProgClient", progname | args | timeout_ | writable | flags);
    79     LOGCALL_STATIC(DB, 
string, 
"ProgClient::get_progcontext", progname | args);
    80     RETURN(
"remote:prog(" + progname + 
" " + args + 
")");
    94 #if defined HAVE_SOCKETPAIR && defined HAVE_FORK   104     if (socketpair(PF_UNIX, SOCK_STREAM|
SOCK_CLOEXEC, 0, sv) < 0) {
   113     vector<string> argvec;
   115     const char **new_argv = 
new const char *[argvec.size() + 2];
   140     int dup_to_first = 0;
   145     dup2(sv[1], dup_to_first);
   152     dup2(dup_to_first, dup_to_first ^ 1);
   155     int stderrfd = 
open(
"/dev/null", O_WRONLY);
   156     if (stderrfd == -1) {
   165     new_argv[0] = progname.c_str();
   166     for (vector<string>::size_type i = 0; i < argvec.size(); ++i) {
   167         new_argv[i + 1] = argvec[i].c_str();
   169     new_argv[argvec.size() + 1] = 0;
   170     execvp(progname.c_str(), 
const_cast<char *
const *
>(new_argv));
   180 #elif defined __WIN32__   181     static unsigned int pipecount = 0;
   184     SNPRINTF(pipename, 
sizeof(pipename),
   185              "\\\\.\\pipe\\xapian-remote-%lx-%lx-%x",
   186              static_cast<unsigned long>(GetCurrentProcessId()),
   187              static_cast<unsigned long>(GetCurrentThreadId()), pipecount++);
   188     pipename[
sizeof(pipename) - 1] = 
'\0';
   190     sprintf(pipename, 
"\\\\.\\pipe\\xapian-remote-%lx-%lx-%x",
   191             static_cast<unsigned long>(GetCurrentProcessId()),
   192             static_cast<unsigned long>(GetCurrentThreadId()), pipecount++);
   195     HANDLE hPipe = CreateNamedPipe(pipename,
   196                                    PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
   198                                    1, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT,
   201     if (hPipe == INVALID_HANDLE_VALUE) {
   204                                    -
int(GetLastError()));
   207     HANDLE hClient = CreateFile(pipename,
   208                                 GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
   209                                 FILE_FLAG_OVERLAPPED, NULL);
   211     if (hClient == INVALID_HANDLE_VALUE) {
   214                                    -
int(GetLastError()));
   217     if (!ConnectNamedPipe(hPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED) {
   220                                    -
int(GetLastError()));
   224     SetHandleInformation(hClient, HANDLE_FLAG_INHERIT, 1);
   227     PROCESS_INFORMATION procinfo;
   228     memset(&procinfo, 0, 
sizeof(PROCESS_INFORMATION));
   230     STARTUPINFO startupinfo;
   231     memset(&startupinfo, 0, 
sizeof(STARTUPINFO));
   232     startupinfo.cb = 
sizeof(STARTUPINFO);
   233     startupinfo.hStdError = hClient;
   234     startupinfo.hStdOutput = hClient;
   235     startupinfo.hStdInput = hClient;
   236     startupinfo.dwFlags |= STARTF_USESTDHANDLES;
   238     string cmdline{progname};
   243     BOOL ok = CreateProcess(progname.c_str(), &cmdline[0], 0, 0, TRUE, 0, 0, 0,
   244                             &startupinfo, &procinfo);
   248                                    -
int(GetLastError()));
   251     CloseHandle(hClient);
   252     CloseHandle(procinfo.hThread);
   253     child = procinfo.hProcess;
   266     waitpid(
child, 0, 0);
   268     WaitForSingleObject(
child, INFINITE);
 void close()
Close the database. 
 
#define LOGCALL_STATIC(CATEGORY, TYPE, FUNC, PARAMS)
 
include <sys/socket.h> with portability workarounds. 
 
Implementation of closefrom() function. 
 
WritableDatabase open()
Construct a WritableDatabase object for a new, empty InMemory database. 
 
void do_close()
Close the socket. 
 
Hierarchy of classes which Xapian can throw as exceptions. 
 
ProgClient(const ProgClient &)
Don't allow copying. 
 
pid_t child
Process id of the child process. 
 
static void split_words(const string &text, vector< string > &words, char ws=' ')
Split a string into a vector of strings, using a given separator character (default space) ...
 
static std::string get_progcontext(const std::string &progname, const std::string &args)
Generate context string for Xapian::Error exception objects. 
 
RemoteDatabase is the baseclass for remote database implementations. 
 
Implementation of RemoteDatabase using a spawned server. 
 
#define LOGCALL_CTOR(CATEGORY, CLASS, PARAMS)
 
Indicates a problem communicating with a remote database. 
 
include <fcntl.h>, but working around broken platforms. 
 
static int run_program(const std::string &progname, const std::string &args, pid_t &child)
Start the child process.