mongodb源码分析
github上下载代码到本地,首先找到程序入口main:在mongod.cpp#if defined(_WIN32)// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters// as main() but encoded in Windows Unicode (UT
·
github上下载代码到本地,首先找到程序入口main:
在mongod.cpp
#if defined(_WIN32)
// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters
// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The
// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent
// and makes them available through the argv() and envp() members. This enables mongoDbMain()
// to process UTF-8 encoded arguments and environment variables without regard to platform.
int wmain(int argc, wchar_t* argvW[]) {
mongo::quickExit(mongo::mongod_main(argc, mongo::WindowsCommandLine(argc, argvW).argv()));
}
#else
int main(int argc, char* argv[]) {
mongo::quickExit(mongo::mongod_main(argc, argv));
}
#endif
我们只关注linux下就行,因为实际运行都是linux下。
首先看mongo::mongod_main,在mongod_main.cpp中,接受启动的参数列表作为形参。
int mongod_main(int argc, char* argv[]) {
//禁止多线程调用
ThreadSafetyContext::getThreadSafetyContext()->forbidMultiThreading();
//设置系统关闭函数(清理工作)
registerShutdownTask(shutdownTask);
//设置同步新号处理函数
setupSignalHandlers();
//随机数种子生成
srand(static_cast<unsigned>(curTimeMicros64()));
Status status = mongo::runGlobalInitializers(std::vector<std::string>(argv, argv + argc));
if (!status.isOK()) {
LOGV2_FATAL_OPTIONS(
20574,
logv2::LogOptions(logv2::LogComponent::kControl, logv2::FatalMode::kContinue),
"Error during global initialization: {error}",
"Error during global initialization",
"error"_attr = status);
quickExit(EXIT_FAILURE);
}
//提高公共服务
auto* service = [] {
try {
auto serviceContextHolder = ServiceContext::make();
auto* serviceContext = serviceContextHolder.get();
setGlobalServiceContext(std::move(serviceContextHolder));
return serviceContext;
} catch (...) {
auto cause = exceptionToStatus();
LOGV2_FATAL_OPTIONS(
20575,
logv2::LogOptions(logv2::LogComponent::kControl, logv2::FatalMode::kContinue),
"Error creating service context: {error}",
"Error creating service context",
"error"_attr = redact(cause));
quickExit(EXIT_FAILURE);
}
}();
setUpCollectionShardingState(service);
setUpCatalog(service);
setUpReplication(service);
setUpObservers(service);
service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service));
ErrorExtraInfo::invariantHaveAllParsers();
startupConfigActions(std::vector<std::string>(argv, argv + argc));
cmdline_utils::censorArgvArray(argc, argv);
if (!initializeServerGlobalState(service))
quickExit(EXIT_FAILURE);
if (!initializeServerSecurityGlobalState(service))
quickExit(EXIT_FAILURE);
// There is no single-threaded guarantee beyond this point.
ThreadSafetyContext::getThreadSafetyContext()->allowMultiThreading();
// Per SERVER-7434, startSignalProcessingThread must run after any forks (i.e.
// initializeServerGlobalState) and before the creation of any other threads
startSignalProcessingThread();
ReadWriteConcernDefaults::create(service, readWriteConcernDefaultsCacheLookupMongoD);
#if defined(_WIN32)
if (ntservice::shouldStartService()) {
ntservice::startService();
// exits directly and so never reaches here either.
}
#endif
//初始化网络
ExitCode exitCode = initAndListen(service, serverGlobalParams.port);
exitCleanly(exitCode);
return 0;
}
接下来看看如何初始化网络,主要用到的是TransportLayerManager
if (!storageGlobalParams.repair) {
//传输层初始化
auto tl =
transport::TransportLayerManager::createWithConfig(&serverGlobalParams, serviceContext);
auto res = tl->setup();
if (!res.isOK()) {
LOGV2_ERROR(20568,
"Error setting up listener: {error}",
"Error setting up listener",
"error"_attr = res);
return EXIT_NET_ERROR;
}
serviceContext->setTransportLayer(std::move(tl));
}
//从实现可以看出传输层用的asio
std::unique_ptr<TransportLayer> TransportLayerManager::createWithConfig(
const ServerGlobalParams* config, ServiceContext* ctx) {
auto sep = ctx->getServiceEntryPoint();
transport::TransportLayerASIO::Options opts(config);
opts.transportMode = transport::Mode::kSynchronous;
ctx->setServiceExecutor(std::make_unique<ServiceExecutorSynchronous>(ctx));
std::vector<std::unique_ptr<TransportLayer>> retVector;
retVector.emplace_back(std::make_unique<transport::TransportLayerASIO>(opts, sep));
return std::make_unique<TransportLayerManager>(std::move(retVector));
}
//然后经过若干行终于启动传输层了
if (!storageGlobalParams.repair) {
start = serviceContext->getTransportLayer()->start();
if (!start.isOK()) {
LOGV2_ERROR(20572,
"Error starting listener: {error}",
"Error starting listener",
"error"_attr = start);
return EXIT_NET_ERROR;
}
}
然后启动监听线程
Status TransportLayerASIO::start() {
stdx::unique_lock lk(_mutex);
// Make sure we haven't shutdown already
invariant(!_isShutdown);
if (_listenerOptions.isIngress()) {
//启动监听线程
_listener.thread = stdx::thread([this] { _runListener(); });
_listener.cv.wait(lk, [&] { return _isShutdown || _listener.active; });
return Status::OK();
}
invariant(_acceptors.empty());
return Status::OK();
}
接受一个新连接,处理session的是ServiceEntryPointMongod
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献5条内容
所有评论(0)