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.