mt_throws Result TcpServer::open () { fd = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); if (fd == INVALID_SOCKET) { exc_throw (WSAException, WSAGetLastError ()); exc_throw (InternalException, InternalException::BackendError); return Result::Failure; } { u_long value = 1; int const res = ioctlsocket (fd, FIONBIO, &value); if (res != 0) { if (res != SOCKET_ERROR) { exc_throw (InternalException, InternalException::BackendMalfunction); logE_ (_func, "ioctlsocket(): unexpected return value: ", res); return Result::Failure; } int const error = WSAGetLastError (); exc_throw (WSAException, error); exc_push (InternalException, InternalException::BackendError); logE_ (_func, "ioctlsocket() failed: ", wsaErrorToString (error)); return Result::Failure; } } if (!_libMary_win32_setsockopt_reuseaddr (fd)) return Result::Failure; return Result::Success; }
mt_throws Result Thread::spawn (bool const joinable) { this->ref (); mutex.lock (); GError *error = NULL; GThread * const tmp_thread = g_thread_create (wrapperThreadFunc, this, joinable ? TRUE : FALSE, &error); this->thread = tmp_thread; mutex.unlock (); if (tmp_thread == NULL) { exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "g_thread_create() failed: ", error->message, error->message ? strlen (error->message) : 0); g_clear_error (&error); this->unref (); return Result::Failure; } return Result::Success; }
Ref<FetchProtocol> SourceManager::getFetchProtocolForUri (ConstMemory const uri) { ConstMemory protocol_name; { Count i = 0; for (Count const i_end = uri.len(); i < i_end; ++i) { if (uri.mem() [i] == ':') break; } protocol_name = uri.region (0, i); } Ref<FetchProtocol> fetch_protocol; { mutex.lock (); FetchProtocolHash::EntryKey const fetch_protocol_key = fetch_protocol_hash.lookup (protocol_name); if (fetch_protocol_key) { fetch_protocol = fetch_protocol_key.getData(); } mutex.unlock (); } if (!fetch_protocol) { logE_ (_func, "Fetch protocol not found: ", protocol_name); return NULL; } return fetch_protocol; }
gpointer Thread::wrapperThreadFunc (gpointer const _self) { Thread * const self = static_cast <Thread*> (_self); try { self->mutex.lock (); Cb<ThreadFunc> const tmp_cb = self->thread_cb; self->mutex.unlock (); tmp_cb.call_ (); } catch (...) { logE_ (_func, "unhandled C++ exception"); } self->mutex.lock (); self->thread_cb.reset (); self->mutex.unlock (); self->unref (); // TODO Release thread-local data, if any // libMary_releaseThreadLocal (); #warning DO DO DO RELEASE !!! return (gpointer) 0; }
bool EventService::acceptOneConnection () { Ref<Session> const session = grab (new (std::nothrow) Session (NULL /* embed_container */)); IpAddress client_addr; { TcpServer::AcceptResult const res = tcp_server->accept (session->tcp_conn, &client_addr); if (res == TcpServer::AcceptResult::Error) { logE_ (_func, "tcp_server.accept() failed: ", exc->toString()); return false; } if (res == TcpServer::AcceptResult::NotAccepted) return false; assert (res == TcpServer::AcceptResult::Accepted); } session->weak_event_service = this; Ref<ServerThreadContext> const thread_ctx = server_ctx->selectThreadContext (); session->weak_thread_ctx = thread_ctx; session->sender->setFrontend (CbDesc<Sender::Frontend> (&sender_frontend, session, session)); session->sender->setConnection (session->tcp_conn); session->sender->setQueue (thread_ctx->getDeferredConnectionSenderQueue()); session->receiver->init (session->tcp_conn, thread_ctx->getDeferredProcessor()); session->line_server->init (session->receiver, CbDesc<LineServer::Frontend> (&line_server_frontend, session, session)); mutex.lock (); session->pollable_key = thread_ctx->getPollGroup()->addPollable (session->tcp_conn->getPollable()); if (!session->pollable_key) { mutex.unlock (); logE_ (_func, "addPollable() failed: ", exc->toString()); return true; } session->session_list_el = session_list.append (session); mutex.unlock (); session->receiver->start (); return true; }
mt_mutex (mutex) mt_throws Result LinePipe::openPipeSession () { assert (!pipe_session); pipe_session = grab (new (std::nothrow) PipeSession (NULL /* embed_container */)); pipe_session->weak_line_pipe = this; bool opened = false; if (!pipe_session->line_file->open (filename->mem(), 0 /* open_flags */, FileAccessMode::ReadOnly)) { goto _close; } opened = true; pipe_session->line_receiver->init (pipe_session->line_file, deferred_processor); pipe_session->line_server->init (pipe_session->line_receiver, CbDesc<LineServer::Frontend> (&line_frontend, pipe_session, pipe_session), max_line_len); pipe_session->pollable_key = poll_group->addPollable (pipe_session->line_file->getPollable()); if (!pipe_session->pollable_key) goto _close; pipe_session->line_receiver->start (); return Result::Success; _close: { StRef<String> const error_str = exc->toString(); if (!prv_error_str || !equal (prv_error_str->mem(), error_str ? error_str->mem() : ConstMemory())) { prv_error_str = st_grab (new (std::nothrow) String (error_str ? error_str->mem() : ConstMemory())); logW_ (_func, "could not open pipe\"", filename, "\": ", error_str); } } ExceptionBuffer * const exc_buf = exc_swap_nounref (); if (opened) { if (!pipe_session->line_file->close (false /* flush_data */)) logE_ (_func, "file.close() failed: ", exc->toString()); } pipe_session = NULL; if (timers) { reopen_timer = timers->addTimer_microseconds ( CbDesc<Timers::TimerCallback> (reopenTimerTick, this, this), reopen_timeout_millisec * 1000, false /* periodical */); } exc_set_noref (exc_buf); return Result::Failure; }
PollPollGroup::~PollPollGroup () { mutex.lock (); { PollableList::iter iter (pollable_list); while (!pollable_list.iter_done (iter)) { PollableEntry * const pollable_entry = pollable_list.iter_next (iter); assert (pollable_entry->activated); delete pollable_entry; } } { PollableList::iter iter (inactive_pollable_list); while (!inactive_pollable_list.iter_done (iter)) { PollableEntry * const pollable_entry = inactive_pollable_list.iter_next (iter); assert (!pollable_entry->activated); delete pollable_entry; } } mutex.unlock (); for (int i = 0; i < 2; ++i) { if (trigger_pipe [i] != -1) { for (;;) { int const res = close (trigger_pipe [i]); if (res == -1) { if (errno == EINTR) continue; logE_ (_func, "trigger_pipe[", i, "]: close() failed: ", errnoString (errno)); } else if (res != 0) { logE_ (_func, "trigger_pipe[", i, "]: close(): unexpected return value: ", res); } break; } } } }
Result FileNameToUnixTimeStamp::Convert(const StRef<String> & fileName, /*output*/ Time & timeOfRecord) { if(fileName == NULL || !fileName->len()) return Result::Failure; Result res = Result::Success; std::string stdStr(fileName->cstr()); std::string delimiter1 = "_"; std::string delimiter2 = "."; size_t pos = 0; std::string token; pos = stdStr.rfind(delimiter1); if(pos != std::string::npos) { token = stdStr.substr(0, pos); stdStr.erase(0, pos + delimiter1.length()); pos = stdStr.rfind(delimiter2); if(pos != std::string::npos) { token = stdStr.substr(0, pos); res = strToUint64_safe(token.c_str(), &timeOfRecord); } else { logE_(_func_,"Didn't find '.' symbol in file_name = ", fileName->mem()); res = Result::Failure; } } else { logE_(_func_,"Didn't find '_' symbol in file_name = ", fileName->mem()); res = Result::Failure; } return res; }
mt_mutex (mutex) void LinePipe::releasePipeSession () { if (!pipe_session) return; assert (pipe_session->pollable_key); poll_group->removePollable (pipe_session->pollable_key); pipe_session->pollable_key = NULL; if (!pipe_session->line_file->close (false /* flush_data */)) logE_ (_func, "could not close pipe file: ", exc->toString()); pipe_session = NULL; }
void libMaryInit () { { static bool initialized = false; if (initialized) { return; } initialized = true; } // Setting numeric locale for snprintf() to behave uniformly in all cases. // Specifically, we need dot ('.') to be used as a decimal separator. if (setlocale (LC_NUMERIC, "C") == NULL) fprintf (stderr, "WARNING: Could not set LC_NUMERIC locale to \"C\"\n"); #ifndef LIBMARY_PLATFORM_WIN32 // GStreamer calls setlocale(LC_ALL, ""), which is lame. We fight this with setenv(). if (setenv ("LC_NUMERIC", "C", 1 /* overwrite */) == -1) perror ("WARNING: Could not set LC_NUMERIC environment variable to \"C\""); #endif #ifdef LIBMARY_MT_SAFE #ifdef LIBMARY__OLD_GTHREAD_API if (!g_thread_get_initialized ()) g_thread_init (NULL); #endif #endif initStatCounters (); _libMary_stat = new (std::nothrow) Stat; assert (_libMary_stat); libMary_threadLocalInit (); libMary_platformInit (); // log*() logging is now available. if (!updateTime ()) logE_ (_func, exc->toString()); #ifdef LIBMARY_ENABLE_MWRITEV libMary_mwritevInit (); #endif randomSetSeed ((Uint32) getTimeMicroseconds()); }
StRef<String> DefaultNamingScheme::getPath (ConstMemory const channel_name, const timeval & tv, Time * const ret_next_unixtime_sec) { const Time unixtime_sec = tv.tv_sec; struct tm tm; if (!unixtimeToStructTm (unixtime_sec, &tm)) { logE_ (_func, "unixtimeToStructTm() failed"); return NULL; } // logD_ (_func, "unixtimeToStructTm() cur_unixtime_sec: ", cur_unixtime_sec); // logD_ (_func, "unixtimeToStructTm() unixtime_sec: ", unixtime_sec); // logD_ (_func, "unixtimeToStructTm() tv.tv_sec: ", tv.tv_sec, ", tv.tv_usec: ", tv.tv_usec); //double time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond unsigned const day_duration = 3600 * 24; unsigned const hour_duration = 3600; unsigned const minute_duration = 60; Time file_duration_sec_local = file_duration_sec; Format fmt; fmt.min_digits = 2; StRef<String> res_str; // previous file gmtime next file boundary // boundary | | // | v | // ______|____________________________|_____________________ // \____________/^ // | | // | unixtime // | // offset if (file_duration_sec_local >= day_duration) { // The offset is approximate but close. // There may a few seconds of difference, and we don't account for that here, // rounding to the neares day instead. // unsigned const offset = tm.tm_hour * 3600 + tm.tm_min * 60 + tm.tm_sec; // *ret_next_unixtime_sec = unixtime_sec + (day_duration - offset); // res_str = st_makeString (tm.tm_year + 1900, "/", fmt, tm.tm_mon + 1, "/", tm.tm_mday); // } else file_duration_sec_local = day_duration - 1; } if (file_duration_sec_local < minute_duration) { file_duration_sec_local = minute_duration; } if (file_duration_sec_local >= hour_duration) { unsigned hours = file_duration_sec_local / hour_duration; unsigned const offset = (tm.tm_hour % hours) * 3600 + tm.tm_min * 60 + tm.tm_sec; *ret_next_unixtime_sec = unixtime_sec + (hours * 3600 - offset); //logD_ (_func, "tm.tm_mday: ", tm.tm_mday, ", tm.tm_hour: ", tm.tm_hour, ", hour: ", tm.tm_hour - tm.tm_hour % hours); res_str = st_makeString (tm.tm_year + 1900, "/", fmt, tm.tm_mon + 1, "/", tm.tm_mday, "/", tm.tm_hour/* - tm.tm_hour % hours*/, tm.tm_min, tm.tm_sec); } else // (file_duration_sec_local >= minute_duration) { unsigned minutes = file_duration_sec_local / minute_duration; unsigned const offset = (tm.tm_min % minutes) * 60 + tm.tm_sec; *ret_next_unixtime_sec = unixtime_sec + (minutes * 60 - offset); res_str = st_makeString (tm.tm_year + 1900, "/", fmt, tm.tm_mon + 1, "/", tm.tm_mday, "/", tm.tm_hour, tm.tm_min/* - tm.tm_min % minutes*/, tm.tm_sec); } // else { // unsigned const offset = tm.tm_sec % file_duration_sec_local; // *ret_next_unixtime_sec = unixtime_sec + (file_duration_sec_local - offset); // res_str = st_makeString (tm.tm_year + 1900, "/", fmt, tm.tm_mon + 1, "/", tm.tm_mday, "/", tm.tm_hour, tm.tm_min, tm.tm_sec - offset); // } if (*ret_next_unixtime_sec == unixtime_sec) *ret_next_unixtime_sec = unixtime_sec + 1; Time unixtimeprefix = (Time)tv.tv_sec * 1000000000LL + (Time)tv.tv_usec * 1000; res_str = st_makeString (channel_name, "/", res_str, "_", unixtimeprefix); // logD_ (_func, "res_str: ", res_str); return res_str; }
mt_throws Result PollPollGroup::poll (Uint64 const timeout_microsec) { Time const start_microsec = getTimeMicroseconds (); Result ret_res = Result::Success; SelectedList selected_list; for (;;) { selected_list.clear (); Count cur_num_pollables = 1; struct pollfd pollfds [num_pollables]; pollfds [0].fd = trigger_pipe [0]; pollfds [0].events = POLLIN; { mutex.lock (); PollableList::iter iter (pollable_list); while (!pollable_list.iter_done (iter)) { PollableEntry * const pollable_entry = pollable_list.iter_next (iter); selected_list.append (pollable_entry); pollfds [cur_num_pollables].fd = pollable_entry->fd; pollfds [cur_num_pollables].events = #ifdef __linux__ POLLRDHUP; #else 0; #endif if (pollable_entry->need_input) pollfds [cur_num_pollables].events |= POLLIN; if (pollable_entry->need_output) pollfds [cur_num_pollables].events |= POLLOUT; pollable_entry->ref (); ++cur_num_pollables; } assert (cur_num_pollables == num_pollables + 1); mutex.unlock (); } Time elapsed_microsec; int nfds; { Time cur_microsec = getTimeMicroseconds (); if (cur_microsec < start_microsec) cur_microsec = start_microsec; elapsed_microsec = cur_microsec - start_microsec; int timeout; if (!got_deferred_tasks) { if (timeout_microsec != (Uint64) -1) { if (timeout_microsec > elapsed_microsec) { Uint64 const tmp_timeout = (timeout_microsec - elapsed_microsec) / 1000; timeout = (int) tmp_timeout; if ((Uint64) timeout != tmp_timeout || timeout < 0) timeout = Int_Max - 1; if (timeout == 0) timeout = 1; } else { timeout = 0; } } else { timeout = -1; } } else { timeout = 0; } mutex.lock (); if (triggered || timeout == 0) { block_trigger_pipe = true; timeout = 0; } else { block_trigger_pipe = false; } mutex.unlock (); nfds = ::poll (pollfds, cur_num_pollables, timeout); if (nfds == -1) { if (errno == EINTR) { SelectedList::iter iter (selected_list); mutex.lock (); while (!selected_list.iter_done (iter)) { PollableEntry * const pollable_entry = selected_list.iter_next (iter); pollable_entry->unref (); } mutex.unlock (); // Re-initializing pollfds. continue; } exc_throw (PosixException, errno); exc_push (InternalException, InternalException::BackendError); logE_ (_func, "poll() failed: ", errnoString (errno)); ret_res = Result::Failure; goto _poll_interrupted; } else if (nfds < 0) { logE_ (_func, "unexpected return value from poll(): ", nfds); exc_throw (InternalException, InternalException::BackendMalfunction); ret_res = Result::Failure; goto _poll_interrupted; } } mutex.lock (); block_trigger_pipe = true; bool const was_triggered = triggered; triggered = false; mutex.unlock (); got_deferred_tasks = false; if (frontend) frontend.call (frontend->pollIterationBegin); bool trigger_pipe_ready = false; { if (pollfds [0].revents & (POLLIN | POLLERR | POLLHUP #ifdef __linux__ | POLLRDHUP #endif )) trigger_pipe_ready = true; mutex.lock (); SelectedList::iter iter (selected_list); Count i = 1; while (!selected_list.iter_done (iter)) { PollableEntry * const pollable_entry = selected_list.iter_next (iter); if (nfds > 0 && pollable_entry->valid) { Uint32 event_flags = 0; if (pollfds [i].revents & POLLNVAL) { logW_ (_func, "POLLNVAL for pollable_entry " "0x", fmt_hex, (UintPtr) pollable_entry, ", " "fd ", pollable_entry->fd, " (", pollfds [i].fd, ")"); ++i; continue; } if (pollfds [i].revents & POLLIN) { pollable_entry->need_input = false; event_flags |= PollGroup::Input; } if (pollfds [i].revents & POLLOUT) { pollable_entry->need_output = false; event_flags |= PollGroup::Output; } if (pollfds [i].revents & POLLHUP #ifdef __linux__ || pollfds [i].revents & POLLRDHUP #endif ) { event_flags |= PollGroup::Hup; } if (pollfds [i].revents & POLLERR) { event_flags |= PollGroup::Error; } if (event_flags) { mutex.unlock (); pollable_entry->pollable.call (pollable_entry->pollable->processEvents, /*(*/ event_flags /*)*/); mutex.lock (); } } pollable_entry->unref (); ++i; } assert (i == cur_num_pollables); mutex.unlock (); } if (frontend) { bool extra_iteration_needed = false; frontend.call_ret (&extra_iteration_needed, frontend->pollIterationEnd); if (extra_iteration_needed) got_deferred_tasks = true; } if (trigger_pipe_ready) { if (!commonTriggerPipeRead (trigger_pipe [0])) { logF_ (_func, "commonTriggerPipeRead() failed: ", exc->toString()); return Result::Failure; } break; } if (was_triggered) break; if (elapsed_microsec >= timeout_microsec) { // Timeout expired. break; } } return ret_res; _poll_interrupted: SelectedList::iter iter (selected_list); mutex.lock (); while (!selected_list.iter_done (iter)) { PollableEntry * const pollable_entry = selected_list.iter_next (iter); pollable_entry->unref (); } mutex.unlock (); return ret_res; }
mt_throws Result loadModule (ConstMemory const filename, void * const app_specific) { #ifdef LIBMARY_GLIB GModule * const module = g_module_open ((gchar const*) makeString (filename)->cstr(), (GModuleFlags) (G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL)); if (!module) { exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "failed to open module ", filename, ": ", g_module_error()); return Result::Failure; } ModuleInitFunc init_ptr; if (!g_module_symbol (module, "libMary_moduleInit_wrapper", (gpointer*) &init_ptr)) { exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "failed to open module ", filename, ": " "g_module_symbol (\"libMary_moduleInit_wrapper\") failed: ", g_module_error()); return Result::Failure; } if (!init_ptr (app_specific)) { logE_ (_func, "could notd initialize module ", filename); return Result::Failure; } return Result::Success; #else libraryLock (); void * const handle = dlopen ( #ifdef LIBMARY_PLATFORM_MACOSX makeString (filename, ".0.dylib")->cstr(), #else makeString (filename, ".so")->cstr(), #endif RTLD_LAZY); if (!handle) { char const * const err_str = dlerror (); libraryUnlock (); exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "dlopen (", filename, ") failed: ", err_str); return Result::Failure; } dlerror (); // Clearing any old error conditions. See man dlsym(3). void * const init_ptr = dlsym (handle, "libMary_moduleInit"); if (!init_ptr) { char const * const err_str = dlerror (); libraryUnlock (); exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "dlsym (", filename, ", libMary_moduleInit) failed: ", err_str); return Result::Failure; } libraryUnlock (); bool const res = ((ModuleInitFunc) init_ptr) (app_specific); if (!res) { exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "module init failed: ", filename); } return res ? Result::Success : Result::Failure; #endif }
mt_sync_domain (readTask) bool GetFileSession::readTask (void * const _self) { GetFileSession * const self = static_cast <GetFileSession*> (_self); logD (getfile, _func_); if (self->session_state == SessionState_Header) { MOMENT_SERVER__HEADERS_DATE for (;;) { MediaReader::ReadFrameResult const res = self->media_reader->readMoreData (&read_frame_backend, self); if (res == MediaReader::ReadFrameResult_Failure) { logE_ (_func, "ReadFrameResult_Failure"); ConstMemory msg = "Data retrieval error"; self->sender->send (self->page_pool, true /* do_flush */, // TODO No cache MOMENT_SERVER__500_HEADERS (msg.len()), "\r\n", msg); if (!self->req_is_keepalive) self->sender->closeAfterFlush (); logA_ ("mod_nvr 500 ", self->req_client_addr, " ", self->req_request_line); return false /* do not reschedule */; } bool header_done = false; if (res == MediaReader::ReadFrameResult_NoData) { logD (getfile, _func, "ReadFrameResult_NoData"); if (!self->got_last_audio_ts && !self->got_last_video_ts) { ConstMemory msg = "Requested video data not found"; self->sender->send (self->page_pool, true /* do_flush */, // TODO No cache MOMENT_SERVER__404_HEADERS (msg.len()), "\r\n", msg); if (!self->req_is_keepalive) self->sender->closeAfterFlush (); logA_ ("mod_nvr 404 ", self->req_client_addr, " ", self->req_request_line); return false /* do not reschedule */; } header_done = true; } else if (res == MediaReader::ReadFrameResult_Finish) { logD (getfile, _func, "ReadFrameResult_Finish"); header_done = true; } if (header_done) { self->session_state = SessionState_Data; self->media_reader->reset (); break; } assert (res != MediaReader::ReadFrameResult_BurstLimit); assert (res == MediaReader::ReadFrameResult_Success); } PagePool::PageListInfo const mp4_header = self->mp4_muxer.pass1_complete (self->duration_sec * 1000); { self->sender->send (self->page_pool, true /* do_flush */, // TODO No cache MOMENT_SERVER__OK_HEADERS ( (!self->octet_stream_mime ? ConstMemory ("video/mp4") : ConstMemory ("application/octet-stream")), mp4_header.data_len + self->mp4_muxer.getTotalDataSize()), "\r\n"); logD_ (_func, "CONTENT-LENGTH: ", mp4_header.data_len + self->mp4_muxer.getTotalDataSize()); if (!self->req_is_keepalive) self->sender->closeAfterFlush (); logA_ ("mod_nvr 200 ", self->req_client_addr, " ", self->req_request_line); } { SenderMessageEntry_Pages * const msg_pages = SenderMessageEntry_Pages::createNew (/*header_len=*/ 0); msg_pages->init (mp4_header.first, self->page_pool, /*msg_offs=*/ 0, mp4_header.data_len); self->sender->sendMessage (msg_pages, true /* do_flush */); } self->transfer_start_time_millisec = getTimeMilliseconds(); self->bytes_transferred += mp4_header.data_len; self->sender->getEventInformer()->subscribe ( CbDesc<Sender::Frontend> (&sender_frontend, self, self)); }
mt_throws Result updateTime () { LibMary_ThreadLocal * const tlocal = libMary_getThreadLocal(); #ifdef LIBMARY_PLATFORM_WIN32 DWORD const win_time_dw = timeGetTime(); if (tlocal->prv_win_time_dw >= win_time_dw) { tlocal->win_time_offs += 0x100000000; } tlocal->prv_win_time_dw = win_time_dw; DWORD const win_time = win_time_dw + tlocal->win_time_offs; Time const new_seconds = (Time) win_time / 1000; Time const new_microseconds = (Time) win_time * 1000; #else #ifdef __MACH__ mach_timespec_t mts; { #warning TODO call host_get_clock_service only once clock_serv_t clk; host_get_clock_service (mach_host_self(), SYSTEM_CLOCK, &clk); clock_get_time (clk, &mts); mach_port_deallocate (mach_task_self(), clk); } Time const new_seconds = mts.tv_sec; Time const new_microseconds = (Uint64) mts.tv_sec * 1000000 + (Uint64) mts.tv_nsec / 1000; #if 0 // Deprecated gint64 const mono_time = g_get_monotonic_time (); Int64 const mono_time = 0; Time const new_seconds = mono_time / 1000000; Time const new_microseconds = mono_time; #endif #else struct timespec ts; // Note that clock_gettime is well-optimized on Linux x86_64 and does not carry // full syscall overhead (depends on system configuration). int const res = clock_gettime (CLOCK_MONOTONIC, &ts); if (res == -1) { exc_throw (PosixException, errno); exc_push (InternalException, InternalException::BackendError); logE_ (_func, "clock_gettime() failed: ", errnoString (errno)); return Result::Failure; } else if (res != 0) { exc_throw (InternalException, InternalException::BackendError); logE_ (_func, "clock_gettime(): unexpected return value: ", res); return Result::Failure; } logD (time, _func, "tv_sec: ", ts.tv_sec, ", tv_nsec: ", ts.tv_nsec); Time const new_seconds = ts.tv_sec; Time const new_microseconds = (Uint64) ts.tv_sec * 1000000 + (Uint64) ts.tv_nsec / 1000; #endif #endif tlocal->time_log_frac = new_microseconds % 1000000 / 100; if (new_seconds >= tlocal->time_seconds) tlocal->time_seconds = new_seconds; else logW_ (_func, "seconds backwards: ", new_seconds, " (was ", tlocal->time_seconds, ")"); if (new_microseconds >= tlocal->time_microseconds) tlocal->time_microseconds = new_microseconds; else logW_ (_func, "microseconds backwards: ", new_microseconds, " (was ", tlocal->time_microseconds, ")"); logD (time, _func, fmt_hex, tlocal->time_seconds, ", ", tlocal->time_microseconds); if (tlocal->saved_monotime < tlocal->time_seconds || tlocal->saved_unixtime == 0) { // Updading saved unixtime once in a minute. if (tlocal->time_seconds - tlocal->saved_monotime >= 60 || tlocal->saved_unixtime == 0) { // Obtaining current unixtime. This is an extra syscall. tlocal->saved_unixtime = time (NULL); tlocal->saved_monotime = tlocal->time_seconds; } // Updating localtime (broken-down time). time_t const cur_unixtime = tlocal->saved_unixtime + (tlocal->time_seconds - tlocal->saved_monotime); tlocal->unixtime = cur_unixtime; // Note that we call tzset() in libMary_posixInit() for localtime_r() to work correctly. #ifdef LIBMARY_PLATFORM_WIN32 #ifdef LIBMARY_WIN32_SECURE_CRT if (localtime_s (&tlocal->localtime, &cur_unixtime) != 0) logF_ (_func, "localtime_s() failed"); #else libraryLock (); struct tm * const tmp_localtime = localtime (&cur_unixtime); if (tmp_localtime) { tlocal->localtime = *tmp_localtime; } libraryUnlock (); if (!tmp_localtime) logF_ (_func, "localtime() failed"); #endif #else // TODO FIXME This lib function is dog-slow and has huge synchronization overhead. localtime_r (&cur_unixtime, &tlocal->localtime); #endif } // long const timezone_abs = timezone >= 0 ? timezone : -timezone; long const timezone_abs = 0; // tlocal->timezone_str [0] = timezone >= 0 ? '+' : '-'; tlocal->timezone_str [0] = '+'; tlocal->timezone_str [1] = '0' + timezone_abs / 36000; tlocal->timezone_str [2] = '0' + timezone_abs / 3600 % 10; tlocal->timezone_str [3] = '0' + timezone_abs / 600 % 6; tlocal->timezone_str [4] = '0' + timezone_abs / 60 % 10; return Result::Success; }
bool RecpathConfig::LoadConfig(const std::string & path_to_config) { logD(recpath, _func_); //m_mutex.lock(); m_configs.clear(); m_bIsEmpty = true; Json::Value root; // will contains the root value after parsing. Json::Reader reader; std::ifstream config_file(path_to_config, std::ifstream::binary); if(!config_file.good()) { //m_mutex.unlock(); logE_(_func_, "fail to load config"); return false; } bool parsingSuccessful = reader.parse( config_file, root, false ); if(!parsingSuccessful) { //m_mutex.unlock(); logE_(_func_, "fail to parse config"); return false; } Json::Value configs = root["configs"]; if(configs.empty()) { //m_mutex.unlock(); logE_(_func_, "fail to find \"configs\" section"); return false; } for( Json::ValueIterator itr = configs.begin() ; itr != configs.end() ; itr++ ) { Json::Value value = (*itr); Json::Value path = value["path"]; // Json::Value quota = value["quota"]; // Json::Value mode = value["mode"]; if(path.empty())// || quota.empty() || mode.empty()) { m_configs.clear(); //m_mutex.unlock(); logE_(_func_, "fail to parse params for section No ", itr.index()); return false; } m_configs[path.asString()] = ConfigParam(); } // dump config in log int i = 0; for(ConfigMap::const_iterator it = m_configs.begin(); it != m_configs.end(); ++it) { logD(recpath, _func_, "PathEntry ", i++); logD(recpath, _func_, "Path: ", it->first.c_str()); // logD(recpath, _func_, "Quota: ", it->second.quota); // logD(recpath, _func_, "Mode: ", it->second.write_mode); } m_configJson = root.toStyledString(); m_bIsInit = true; //m_mutex.unlock(); return true; }
void libMaryInit () { { static bool initialized = false; if (initialized) { return; } initialized = true; } // Setting numeric locale for snprintf() to behave uniformly in all cases. // Specifically, we need dot ('.') to be used as a decimal separator. if (setlocale (LC_NUMERIC, "C") == NULL) fprintf (stderr, "WARNING: Could not set LC_NUMERIC locale to \"C\"\n"); #ifndef LIBMARY_PLATFORM_WIN32 // GStreamer calls setlocale(LC_ALL, ""), which is lame. We fight this with setenv(). if (setenv ("LC_NUMERIC", "C", 1 /* overwrite */) == -1) perror ("WARNING: Could not set LC_NUMERIC environment variable to \"C\""); #endif #ifdef LIBMARY_MT_SAFE #ifdef LIBMARY__OLD_GTHREAD_API if (!g_thread_get_initialized ()) g_thread_init (NULL); #endif #endif _libMary_stat = new Stat; libMary_threadLocalInit (); libMary_platformInit (); // log*() logging is now available. if (!updateTime ()) logE_ (_func, exc->toString()); #ifdef LIBMARY_ENABLE_MWRITEV libMary_mwritevInit (); #endif randomSetSeed ((Uint32) getTime()); #ifdef LIBMARY_PLATFORM_WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); int res = WSAStartup(wVersionRequested, &wsaData); if (res != 0) { logE_ (_func_, "WSAStartup failed"); } else { if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { logE_ (_func_, "Could not find a requested version of Winsock.dll"); WSACleanup(); } else { logD_ (_func_, "The Winsock 2.2 dll was found"); } } #endif }