my_bool my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, int timeout) { switch (event) { case VIO_IO_EVENT_READ: b->events_to_wait_for = MYSQL_WAIT_READ; break; case VIO_IO_EVENT_WRITE: b->events_to_wait_for = MYSQL_WAIT_WRITE; break; case VIO_IO_EVENT_CONNECT: b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT); break; } if (timeout >= 0) { b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT; b->timeout_value= timeout; } if (b->suspend_resume_hook) (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); return (b->events_occurred & MYSQL_WAIT_TIMEOUT) ? 0 : 1; }
ssize_t my_send_async(struct mysql_async_context *b, int fd, const unsigned char *buf, size_t size, int timeout) { ssize_t res; for (;;) { res= send(fd, buf, size, IF_WIN(0, MSG_DONTWAIT)); if (res >= 0 || IS_BLOCKING_ERROR()) return res; b->events_to_wait_for= MYSQL_WAIT_WRITE; if (timeout >= 0) { b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; b->timeout_value= timeout; } if (b->suspend_resume_hook) (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); if (b->events_occurred & MYSQL_WAIT_TIMEOUT) return -1; } }
static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) { int ret; const char* arg; va_list args; DYNAMIC_STRING ds_cmdline; DBUG_ENTER("run_tool"); DBUG_PRINT("enter", ("tool_path: %s", tool_path)); if (init_dynamic_string(&ds_cmdline, IF_WIN("\"", ""), FN_REFLEN, FN_REFLEN)) die("Out of memory"); dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS); dynstr_append(&ds_cmdline, " "); va_start(args, ds_res); while ((arg= va_arg(args, char *))) { /* Options should be os quoted */ if (strncmp(arg, "--", 2) == 0) dynstr_append_os_quoted(&ds_cmdline, arg, NullS); else dynstr_append(&ds_cmdline, arg); dynstr_append(&ds_cmdline, " "); } va_end(args); #ifdef __WIN__ dynstr_append(&ds_cmdline, "\""); #endif DBUG_PRINT("info", ("Running: %s", ds_cmdline.str)); ret= run_command(ds_cmdline.str, ds_res); DBUG_PRINT("exit", ("ret: %d", ret)); dynstr_free(&ds_cmdline); DBUG_RETURN(ret); }
int basestring_vsnprintf(char *str, size_t size, const char *format, va_list ap) { int ret; if (size == 0) { char buf[1]; return basestring_vsnprintf(buf, 1, format, ap); } ret = IF_WIN(_vsnprintf,vsnprintf)(str, size, format, ap); if (ret >= 0 && ret < (int)size) return ret; #ifdef _WIN32 if (ret < 0 && errno == EINVAL) return ret; // otherwise, more than size chars are needed return _vscprintf(format, ap); #else return ret; #endif }
static bool create_directory(const char * path) { BaseString native(path); to_native(native); BaseString tmp(path); Vector<BaseString> list; if (tmp.split(list, "/") == 0) { g_logger.error("Failed to create directory: %s", tmp.c_str()); return false; } BaseString cwd = IF_WIN("","/"); for (unsigned i = 0; i < list.size(); i++) { cwd.append(list[i].c_str()); cwd.append("/"); NdbDir::create(cwd.c_str(), NdbDir::u_rwx() | NdbDir::g_r() | NdbDir::g_x(), true); } struct stat sbuf; if (lstat(native.c_str(), &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { g_logger.error("Failed to create directory: %s (%s)", native.c_str(), cwd.c_str()); return false; } return true; }
int CPCD::Process::start() { /* We need to fork() twice, so that the second child (grandchild?) can * become a daemon. The original child then writes the pid file, * so that the monitor knows the pid of the new process, and then * exit()s. That way, the monitor process can pickup the pid, and * the running process is a daemon. * * This is a bit tricky but has the following advantages: * - the cpcd can die, and "reconnect" to the monitored clients * without restarting them. * - the cpcd does not have to wait() for the childs. init(1) will * take care of that. */ logger.info("Starting %d: %s", m_id, m_name.c_str()); m_status = STARTING; int pid = -1; switch(m_processType){ case TEMPORARY:{ #ifndef _WIN32 /** * Simple fork * don't ignore child */ switch(pid = fork()) { case 0: /* Child */ setsid(); writePid(getpgrp()); if(runas(m_runas.c_str()) == 0){ signal(SIGCHLD, SIG_DFL); do_exec(); } _exit(1); break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); m_status = STOPPED; return -1; break; default: /* Parent */ logger.debug("Started temporary %d : pid=%d", m_id, pid); break; } #else //_WIN32 do_exec(); #endif break; } #ifndef _WIN32 case PERMANENT:{ /** * PERMANENT */ switch(fork()) { case 0: /* Child */ signal(SIGCHLD, SIG_IGN); switch(pid = fork()) { case 0: /* Child */ setsid(); writePid(getpgrp()); if(runas(m_runas.c_str()) != 0){ _exit(1); } signal(SIGCHLD, SIG_DFL); do_exec(); _exit(1); /* NOTREACHED */ break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); writePid(-1); _exit(1); break; default: /* Parent */ logger.debug("Started permanent %d : pid=%d", m_id, pid); _exit(0); break; } break; case -1: /* Error */ logger.error("Cannot fork: %s\n", strerror(errno)); m_status = STOPPED; return -1; break; default: /* Parent */ break; } break; } #endif default: logger.critical("Unknown process type"); return -1; } while(readPid() < 0){ sched_yield(); } errno = 0; pid_t pgid = IF_WIN(-1, getpgid(pid)); if(pgid != -1 && pgid != m_pid){ logger.error("pgid and m_pid don't match: %d %d (%d)", pgid, m_pid, pid); } if(isRunning()){ m_status = RUNNING; return 0; } m_status = STOPPED; return -1; }
void CPCD::Process::do_exec() { unsigned i; #ifdef _WIN32 Vector<BaseString> saved; char *cwd = 0; save_environment(m_env.c_str(), saved); #endif setup_environment(m_env.c_str()); char **argv = BaseString::argify(m_path.c_str(), m_args.c_str()); if(strlen(m_cwd.c_str()) > 0) { #ifdef _WIN32 cwd = getcwd(0, 0); if(!cwd) { logger.critical("Couldn't getcwd before spawn"); } #endif int err = chdir(m_cwd.c_str()); if(err == -1) { BaseString err; logger.error("%s: %s\n", m_cwd.c_str(), strerror(errno)); _exit(1); } } #ifndef _WIN32 Vector<BaseString> ulimit; m_ulimit.split(ulimit); for(i = 0; i<ulimit.size(); i++){ if(ulimit[i].trim().length() > 0 && set_ulimit(ulimit[i]) != 0){ _exit(1); } } #endif const char *nul = IF_WIN("nul:", "/dev/null"); int fdnull = open(nul, O_RDWR, 0); if(fdnull == -1) { logger.error("Cannot open `%s': %s\n", nul, strerror(errno)); _exit(1); } BaseString * redirects[] = { &m_stdin, &m_stdout, &m_stderr }; int fds[3]; #ifdef _WIN32 int std_dups[3]; #endif for (i = 0; i < 3; i++) { #ifdef _WIN32 std_dups[i] = dup(i); #endif if (redirects[i]->empty()) { #ifndef DEBUG dup2(fdnull, i); #endif continue; } if((* redirects[i]) == "2>&1" && i == 2){ dup2(fds[1], 2); continue; } /** * Make file */ int flags = 0; int mode = S_IRUSR | S_IWUSR ; if(i == 0){ flags |= O_RDONLY; } else { flags |= O_WRONLY | O_CREAT | O_APPEND; } int f = fds[i]= open(redirects[i]->c_str(), flags, mode); if(f == -1){ logger.error("Cannot redirect %u to/from '%s' : %s\n", i, redirects[i]->c_str(), strerror(errno)); _exit(1); } dup2(f, i); #ifdef _WIN32 close(f); #endif } #ifndef _WIN32 /* Close all filedescriptors */ for(i = STDERR_FILENO+1; (int)i < getdtablesize(); i++) close(i); execv(m_path.c_str(), argv); /* XXX If we reach this point, an error has occurred, but it's kind of hard * to report it, because we've closed all files... So we should probably * create a new logger here */ logger.error("Exec failed: %s\n", strerror(errno)); /* NOTREACHED */ #else // Get full path to cygwins shell FILE *fpipe = _popen("sh -c 'cygpath -w `which sh`'", "rt"); char buf[MAX_PATH]; require(fgets(buf, MAX_PATH - 1, fpipe)); fclose(fpipe); BaseString sh; sh.assign(buf); sh.trim("\n"); sh.append(".exe"); BaseString shcmd; shcmd.assfmt("%s -c '%s %s'", sh.c_str(), m_path.c_str(), m_args.c_str()); PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {sizeof(STARTUPINFO), 0}; si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = (HANDLE)_get_osfhandle(0); si.hStdOutput = (HANDLE)_get_osfhandle(1); si.hStdError = (HANDLE)_get_osfhandle(2); if(!CreateProcessA(sh.c_str(), (LPSTR)shcmd.c_str(), NULL, NULL, TRUE, CREATE_SUSPENDED, // Resumed after assigned to Job NULL, NULL, &si, &pi)) { char* message; DWORD err = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&message, 0, NULL ); logger.error("CreateProcess failed, error: %d, message: '%s'", err, message); LocalFree(message); } HANDLE proc = pi.hProcess; require(proc); // Job control require(m_job = CreateJobObject(0, 0)); require(AssignProcessToJobObject(m_job, proc)); // Resum process after it has been added to Job ResumeThread(pi.hThread); CloseHandle(pi.hThread); // go back up to original cwd if(chdir(cwd)) { logger.critical("Couldn't go back to saved cwd after spawn()"); logger.critical("errno: %d, strerror: %s", errno, strerror(errno)); } free(cwd); // get back to original std i/o for(i = 0; i < 3; i++) { dup2(std_dups[i], i); close(std_dups[i]); } for (i = 0; i < saved.size(); i++) { putenv(saved[i].c_str()); } logger.debug("'%s' has been started", shcmd.c_str()); DWORD exitcode; BOOL result = GetExitCodeProcess(proc, &exitcode); //maybe a short running process if (result && exitcode != 259) { m_status = STOPPED; logger.warning("Process terminated early"); } int pid = GetProcessId(proc); if (!pid) logger.critical("GetProcessId failed, error: %d!", GetLastError()); logger.debug("new pid %d", pid); CloseHandle(proc); m_status = RUNNING; writePid(pid); #endif close(fdnull); }
void ndbd_run(bool foreground, int report_fd, const char* connect_str, int force_nodeid, const char* bind_address, bool no_start, bool initial, bool initialstart, unsigned allocated_nodeid) { #ifdef _WIN32 { char shutdown_event_name[32]; _snprintf(shutdown_event_name, sizeof(shutdown_event_name), "ndbd_shutdown_%d", GetCurrentProcessId()); g_shutdown_event = CreateEvent(NULL, TRUE, FALSE, shutdown_event_name); if (g_shutdown_event == NULL) { g_eventLogger->error("Failed to create shutdown event, error: %d", GetLastError()); ndbd_exit(1); } HANDLE thread = CreateThread(NULL, 0, &shutdown_thread, NULL, 0, NULL); if (thread == NULL) { g_eventLogger->error("couldn't start shutdown thread, error: %d", GetLastError()); ndbd_exit(1); } } #endif if (foreground) g_eventLogger->info("Ndb started in foreground"); if (report_fd) { g_eventLogger->debug("Opening report stream on fd: %d", report_fd); // Open a stream for sending extra status to angel if (!(angel_info_w = fdopen(report_fd, "w"))) { g_eventLogger->error("Failed to open stream for reporting " "to angel, error: %d (%s)", errno, strerror(errno)); ndbd_exit(-1); } } else { // No reporting requested, open /dev/null const char* dev_null = IF_WIN("nul", "/dev/null"); if (!(angel_info_w = fopen(dev_null, "w"))) { g_eventLogger->error("Failed to open stream for reporting to " "'%s', error: %d (%s)", dev_null, errno, strerror(errno)); ndbd_exit(-1); } } globalEmulatorData.create(); Configuration* theConfig = globalEmulatorData.theConfiguration; if(!theConfig->init(no_start, initial, initialstart)) { g_eventLogger->error("Failed to init Configuration"); ndbd_exit(-1); } theConfig->fetch_configuration(connect_str, force_nodeid, bind_address, allocated_nodeid); if (NdbDir::chdir(NdbConfig_get_path(NULL)) != 0) { g_eventLogger->warning("Cannot change directory to '%s', error: %d", NdbConfig_get_path(NULL), errno); // Ignore error } theConfig->setupConfiguration(); if (get_multithreaded_config(globalEmulatorData)) ndbd_exit(-1); systemInfo(* theConfig, * theConfig->m_logLevel); NdbThread* pWatchdog = globalEmulatorData.theWatchDog->doStart(); { /* * Memory allocation can take a long time for large memory. * * So we want the watchdog to monitor the process of initial allocation. */ Uint32 watchCounter; watchCounter = 9; // Means "doing allocation" globalEmulatorData.theWatchDog->registerWatchedThread(&watchCounter, 0); if (init_global_memory_manager(globalEmulatorData, &watchCounter)) ndbd_exit(1); globalEmulatorData.theWatchDog->unregisterWatchedThread(0); } globalEmulatorData.theThreadConfig->init(); #ifdef VM_TRACE // Create a signal logger before block constructors char *buf= NdbConfig_SignalLogFileName(globalData.ownId); NdbAutoPtr<char> tmp_aptr(buf); FILE * signalLog = fopen(buf, "a"); globalSignalLoggers.setOwnNodeId(globalData.ownId); globalSignalLoggers.setOutputStream(signalLog); #if 1 // to log startup { const char* p = NdbEnv_GetEnv("NDB_SIGNAL_LOG", (char*)0, 0); if (p != 0) { char buf[200]; BaseString::snprintf(buf, sizeof(buf), "BLOCK=%s", p); for (char* q = buf; *q != 0; q++) *q = toupper(toascii(*q)); globalSignalLoggers.log(SignalLoggerManager::LogInOut, buf); globalData.testOn = 1; assert(signalLog != 0); fprintf(signalLog, "START\n"); fflush(signalLog); } } #endif #endif // Load blocks (both main and workers) globalEmulatorData.theSimBlockList->load(globalEmulatorData); // Set thread concurrency for Solaris' light weight processes int status; status = NdbThread_SetConcurrencyLevel(30); assert(status == 0); catchsigs(foreground); /** * Do startup */ switch(globalData.theRestartFlag){ case initial_state: globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI); break; case perform_start: globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI); globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING); break; default: assert("Illegal state globalData.theRestartFlag" == 0); } globalTransporterRegistry.startSending(); globalTransporterRegistry.startReceiving(); if (!globalTransporterRegistry.start_service(*globalEmulatorData.m_socket_server)){ ndbout_c("globalTransporterRegistry.start_service() failed"); ndbd_exit(-1); } // Re-use the mgm handle as a transporter if(!globalTransporterRegistry.connect_client( theConfig->get_config_retriever()->get_mgmHandlePtr())) ERROR_SET(fatal, NDBD_EXIT_CONNECTION_SETUP_FAILED, "Failed to convert mgm connection to a transporter", __FILE__); NdbThread* pTrp = globalTransporterRegistry.start_clients(); if (pTrp == 0) { ndbout_c("globalTransporterRegistry.start_clients() failed"); ndbd_exit(-1); } NdbThread* pSockServ = globalEmulatorData.m_socket_server->startServer(); globalEmulatorData.theConfiguration->addThread(pTrp, SocketClientThread); globalEmulatorData.theConfiguration->addThread(pWatchdog, WatchDogThread); globalEmulatorData.theConfiguration->addThread(pSockServ, SocketServerThread); // theConfig->closeConfiguration(); { NdbThread *pThis = NdbThread_CreateObject(0); Uint32 inx = globalEmulatorData.theConfiguration->addThread(pThis, MainThread); globalEmulatorData.theThreadConfig->ipControlLoop(pThis, inx); globalEmulatorData.theConfiguration->removeThreadId(inx); } NdbShutdown(0, NST_Normal); ndbd_exit(0); }
mode_t NdbDir::o_r(void) { return IF_WIN(0, S_IROTH); };
mode_t NdbDir::g_x(void) { return IF_WIN(0, S_IXGRP); };
mode_t NdbDir::g_w(void) { return IF_WIN(0, S_IWGRP); };
mode_t NdbDir::g_r(void) { return IF_WIN(0, S_IRGRP); };
mode_t NdbDir::u_x(void) { return IF_WIN(0, S_IXUSR); };
mode_t NdbDir::u_w(void) { return IF_WIN(0, S_IWUSR); };
mode_t NdbDir::u_r(void) { return IF_WIN(0, S_IRUSR); };
int main(int argc, char **argv) { char self_name[FN_REFLEN]; MY_INIT(argv[0]); #if __WIN__ if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0) #endif { strncpy(self_name, argv[0], FN_REFLEN); } if (init_dynamic_string(&ds_args, "", 512, 256) || init_dynamic_string(&conn_args, "", 512, 256)) die("Out of memory"); if (load_defaults("my", load_default_groups, &argc, &argv)) die(NULL); defaults_argv= argv; /* Must be freed by 'free_defaults' */ if (handle_options(&argc, &argv, my_long_options, get_one_option)) die(NULL); if (debug_info_flag) my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; if (debug_check_flag) my_end_arg= MY_CHECK_ERROR; if (tty_password) { opt_password= get_tty_password(NullS); /* add password to defaults file */ dynstr_append_os_quoted(&ds_args, "--password="******" "); } /* add user to defaults file */ dynstr_append_os_quoted(&ds_args, "--user="******" "); /* Find mysql */ find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name); if (!opt_systables_only) { /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); } else { if (!opt_silent) printf("The --upgrade-system-tables option was used, databases won't be touched.\n"); } /* Read the mysql_upgrade_info file to check if mysql_upgrade already has been run for this installation of MySQL */ if (!opt_force && upgrade_already_done()) { printf("This installation of MySQL is already upgraded to %s, " "use --force if you still need to run mysql_upgrade\n", MYSQL_SERVER_VERSION); die(NULL); } if (opt_version_check && check_version_match()) die("Upgrade failed"); /* Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ if ((!opt_systables_only && (run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade())) || run_sql_fix_privilege_tables()) { /* The upgrade failed to complete in some way or another, significant error message should have been printed to the screen */ die("Upgrade failed" ); } verbose("OK"); /* Create a file indicating upgrade has been performed */ create_mysql_upgrade_info_file(); free_used_memory(); my_end(my_end_arg); exit(0); }
int main(int argc, char **argv) { char self_name[FN_REFLEN]; MY_INIT(argv[0]); #if __WIN__ if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0) #endif { strncpy(self_name, argv[0], FN_REFLEN); } if (init_dynamic_string(&ds_args, "", 512, 256) || init_dynamic_string(&conn_args, "", 512, 256)) die("Out of memory"); if (load_defaults("my", load_default_groups, &argc, &argv)) die(NULL); defaults_argv= argv; /* Must be freed by 'free_defaults' */ if (handle_options(&argc, &argv, my_long_options, get_one_option)) die(NULL); if (debug_info_flag) my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; if (debug_check_flag) my_end_arg= MY_CHECK_ERROR; if (tty_password) { opt_password= get_tty_password(NullS); /* add password to defaults file */ dynstr_append_os_quoted(&ds_args, "--password="******" "); } /* add user to defaults file */ dynstr_append_os_quoted(&ds_args, "--user="******" "); /* Find mysql */ find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name); /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); if (opt_systables_only && !opt_silent) printf("The --upgrade-system-tables option was used, user tables won't be touched.\n"); /* Read the mysql_upgrade_info file to check if mysql_upgrade already has been run for this installation of MySQL */ if (!opt_force && upgrade_already_done()) { printf("This installation of MySQL is already upgraded to %s, " "use --force if you still need to run mysql_upgrade\n", MYSQL_SERVER_VERSION); goto end; } if (opt_version_check && check_version_match()) die("Upgrade failed"); upgrade_from_mysql= is_mysql(); /* Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ if (run_mysqlcheck_upgrade(TRUE) || run_mysqlcheck_views() || run_sql_fix_privilege_tables() || run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade(FALSE)) die("Upgrade failed" ); verbose("Phase %d/%d: Running 'FLUSH PRIVILEGES'", ++phase, phases_total); if (run_query("FLUSH PRIVILEGES", NULL, TRUE)) die("Upgrade failed" ); verbose("OK"); /* Create a file indicating upgrade has been performed */ create_mysql_upgrade_info_file(); DBUG_ASSERT(phase == phases_total); end: free_used_memory(); my_end(my_end_arg); exit(0); }
mode_t NdbDir::o_w(void) { return IF_WIN(0, S_IWOTH); };
/** Look for the filename of given tool, with the presumption that it is in the same directory as mysql_upgrade and that the same executable-searching mechanism will be used when we run our sub-shells with popen() later. */ static void find_tool(char *tool_executable_name, const char *tool_name, const char *self_name) { char *last_fn_libchar; DYNAMIC_STRING ds_tmp; DBUG_ENTER("find_tool"); DBUG_PRINT("enter", ("progname: %s", my_progname)); if (init_dynamic_string(&ds_tmp, "", 32, 32)) die("Out of memory"); last_fn_libchar= strrchr(self_name, FN_LIBCHAR); if (last_fn_libchar == NULL) { /* mysql_upgrade was found by the shell searching the path. A sibling next to us should be found the same way. */ strncpy(tool_executable_name, tool_name, FN_REFLEN); } else { int len; /* mysql_upgrade was run absolutely or relatively. We can find a sibling by replacing our name after the LIBCHAR with the new tool name. */ /* When running in a not yet installed build and using libtool, the program(mysql_upgrade) will be in .libs/ and executed through a libtool wrapper in order to use the dynamic libraries from this build. The same must be done for the tools(mysql and mysqlcheck). Thus if path ends in .libs/, step up one directory and execute the tools from there */ if (((last_fn_libchar - 6) >= self_name) && (strncmp(last_fn_libchar - 5, ".libs", 5) == 0) && (*(last_fn_libchar - 6) == FN_LIBCHAR)) { DBUG_PRINT("info", ("Chopping off \".libs\" from end of path")); last_fn_libchar -= 6; } len= last_fn_libchar - self_name; my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s", len, self_name, FN_LIBCHAR, tool_name); } if (opt_verbose) verbose("Looking for '%s' as: %s", tool_name, tool_executable_name); /* Make sure it can be executed */ if (run_tool(tool_executable_name, &ds_tmp, /* Get output from command, discard*/ "--no-defaults", "--help", "2>&1", IF_WIN("> NUL", "> /dev/null"), NULL)) die("Can't execute '%s'", tool_executable_name); dynstr_free(&ds_tmp); DBUG_VOID_RETURN; }
mode_t NdbDir::o_x(void) { return IF_WIN(0, S_IXOTH); };
bool NdbDir::remove_recursive(const char* dir, bool only_contents) { char path[PATH_MAX]; if (basestring_snprintf(path, sizeof(path), "%s%s", dir, DIR_SEPARATOR) < 0) { fprintf(stderr, "Too long path to remove: '%s'\n", dir); return false; } int start_len = strlen(path); const char* name; NdbDir::Iterator iter; loop: { if (iter.open(path) != 0) { fprintf(stderr, "Failed to open iterator for '%s'\n", path); return false; } while ((name = iter.next_entry()) != NULL) { if ((strcmp(".", name) == 0) || (strcmp("..", name) == 0)) continue; int end_len, len = strlen(path); if ((end_len = basestring_snprintf(path + len, sizeof(path) - len, "%s", name)) < 0) { fprintf(stderr, "Too long path detected: '%s'+'%s'\n", path, name); return false; } if (unlink(path) == 0 || NdbDir::remove(path) == true) { path[len] = 0; continue; } iter.close(); // Append ending slash to the string int pos = len + end_len; if (basestring_snprintf(path + pos, sizeof(path) - pos, "%s", DIR_SEPARATOR) < 0) { fprintf(stderr, "Too long path detected: '%s'+'%s'\n", path, DIR_SEPARATOR); return false; } goto loop; } iter.close(); int len = strlen(path); path[len - 1] = 0; // remove ending slash char * prev_slash = strrchr(path, IF_WIN('\\', '/')); if (len > start_len && prev_slash) { // Not done yet, step up one dir level assert(prev_slash > path && prev_slash < path + sizeof(path)); prev_slash[1] = 0; goto loop; } } if (only_contents == false && NdbDir::remove(dir) == false) { fprintf(stderr, "Failed to remove directory '%s', error: %d\n", dir, errno); return false; } return true; }
static int mgmd_main(int argc, char** argv) { NDB_INIT(argv[0]); printf("MySQL Cluster Management Server %s\n", NDB_VERSION_STRING); ndb_opt_set_usage_funcs(short_usage_sub, usage); load_defaults("my",load_default_groups,&argc,&argv); defaults_argv= argv; /* Must be freed by 'free_defaults' */ int ho_error; #ifndef DBUG_OFF opt_debug= IF_WIN("d:t:i:F:o,c:\\ndb_mgmd.trace", "d:t:i:F:o,/tmp/ndb_mgmd.trace"); #endif if ((ho_error=handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option))) mgmd_exit(ho_error); if (opts.interactive || opts.non_interactive || opts.print_full_config) { opts.daemon= 0; } if (opts.mycnf && opts.config_filename) { fprintf(stderr, "ERROR: Both --mycnf and -f is not supported\n"); mgmd_exit(1); } if (opt_nowait_nodes) { int res = parse_mask(opt_nowait_nodes, opts.nowait_nodes); if(res == -2 || (res > 0 && opts.nowait_nodes.get(0))) { fprintf(stderr, "ERROR: Invalid nodeid specified in nowait-nodes: '%s'\n", opt_nowait_nodes); mgmd_exit(1); } else if (res < 0) { fprintf(stderr, "ERROR: Unable to parse nowait-nodes argument: '%s'\n", opt_nowait_nodes); mgmd_exit(1); } } /* Setup use of event logger */ g_eventLogger->setCategory(opt_logname); /* Output to console initially */ g_eventLogger->createConsoleHandler(); #ifdef _WIN32 /* Output to Windows event log */ g_eventLogger->createEventLogHandler("MySQL Cluster Management Server"); #endif if (opts.verbose) g_eventLogger->enable(Logger::LL_ALL); // --verbose turns on everything /** Install signal handler for SIGPIPE Done in TransporterFacade as well.. what about Configretriever? */ #if !defined NDB_WIN32 signal(SIGPIPE, SIG_IGN); #endif while (!g_StopServer) { mgm= new MgmtSrvr(opts); if (mgm == NULL) { g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr"); mgmd_exit(1); } /* Init mgm, load or fetch config */ if (!mgm->init()) { delete mgm; mgmd_exit(1); } if (NdbDir::chdir(NdbConfig_get_path(NULL)) != 0) { g_eventLogger->warning("Cannot change directory to '%s', error: %d", NdbConfig_get_path(NULL), errno); // Ignore error } if (opts.daemon) { NodeId localNodeId= mgm->getOwnNodeId(); if (localNodeId == 0) { g_eventLogger->error("Couldn't get own node id"); delete mgm; mgmd_exit(1); } char *lockfile= NdbConfig_PidFileName(localNodeId); char *logfile= NdbConfig_StdoutFileName(localNodeId); if (ndb_daemonize(lockfile, logfile)) { g_eventLogger->error("Couldn't start as daemon, error: '%s'", ndb_daemon_error); mgmd_exit(1); } } /* Start mgm services */ if (!mgm->start()) { delete mgm; mgmd_exit(1); } if (opts.interactive) { int port= mgm->getPort(); BaseString con_str; if(opts.bind_address) con_str.appfmt("host=%s:%d", opts.bind_address, port); else con_str.appfmt("localhost:%d", port); Ndb_mgmclient com(con_str.c_str(), 1); while(!g_StopServer) { if (!read_and_execute(&com, "ndb_mgm> ", 1)) g_StopServer = true; } } else { g_eventLogger->info("MySQL Cluster Management Server %s started", NDB_VERSION_STRING); while (!g_StopServer) NdbSleep_MilliSleep(500); } g_eventLogger->info("Shutting down server..."); delete mgm; g_eventLogger->info("Shutdown complete"); if(g_RestartServer) { g_eventLogger->info("Restarting server..."); g_RestartServer= g_StopServer= false; } } mgmd_exit(0); return 0; }