MDSRank与MDSDaemon一起构成了MDS进程的核心处理类。

=====================MDSRankDispatcher相关=========================

MDSRankDispatcher是MDSRank与MDSDaemon的接口类,MDSRankDispatcher就是给MDSDaemon用的。

MDSRankDispatcher::init()

|__update_log_config()                 从配置文件中读取log配置以及更新log配置

|__create_logger()                         创建logger

|__创建PerfCounterBuilder类实例且初始化该类实例

|__MDLog::create_logger()

|__Server::create_logger()

|__MDCache::register_perfcounters()

|__handle_osd_map()

|__对于snapserver不为空,则调用SnapServer::check_osd_map()对已经purged的和未purge的snap进行处理

|__Server::handle_osd_map()

|__检查MDSRank::Objecter对应的OSDMap中所有的osd是否包含CEPH_OSDMAP_FULL标识

|__MDCache::notify_osdmap_changed()

|__StrayManager::update_op_limit()

|__Objecter::maybe_request_map()

|__MonClient::sub_want(“osdmap”)

|__MonClient::renew_subs()                    调用MonClient向Monitor节点索取OSDMap

|__progress_thread.create()                              创建ProgressThread线程

|__Finisher::start()

MDSRankDispatcher::tick()

|__heartbeat_reset()

|__g_ceph_context->get_heartbeat_map()->reset_timeout()     重置heartbeat超时时间,避免被monitor kill

|__check_ops_in_flight()

|__op_tracker.check_ops_in_flight()          从op_tracker中读取到所有in_flight的操作名称

|__遍历所有处于in_flight的操作名称且输出到clog

|__progress_thread.signal()                              唤醒progress_thread线程

|__MDLog::flush()                                             flush所有log

|__MDS进程状态处于active或stopping

|__MDCache::trim()          周期性的trim cache

|__MDLog::trim()               周期性的trim log

|__更新logger

|__对于当前处于active或stopping或clientreplay状态

|__Server::find_idle_sessions()

|__locker->tick()

|__对于当前处于reconnect状态

|__Server::reconnect_tick()

|__对于当前处于active状态

|__MDBalancer::tick()

|__MDCache::find_stale_fragment_freeze()

|__MDCache::migrator::find_stale_export_freeze()

|__SnapServer::check_osd_map()

|__Beacon::notify_health()

MDSRankDispatcher::shutdown()

|__设置stopping=true

|__SafeTimer::shutdown()               关闭定时器

|__MDLog::shutdown()                    关闭MDLog

|__Finisher::stop()                            关闭Finisher

|__MDCache::shutdown()                关闭MDCache

|__Objecter::shutdown()                  关闭Objecter

|__MonClient::shutdown()                关闭MonClient

|__op_tracker.on_shutdown()          回调op_tracker的shutdown回调函数

|__Messenger::shutdown()               关闭Messenger

|__若heartbeat_handle_d不为空,则调用get_heartbeat_map()->remove_worker()来删除这个handle

MDSRankDispatcher::ms_dispatch()

|__inc_dispatch_depth()

|___dipsatch()                                   调用_dispatch()函数做核心分发处理

|__dec_dispatch_depth()

==========================消息dispatch相关===================================

MDSRank::retry_dispatch()

|__inc_dispatch_depth()

|___dispatch()

|__dec_dispatch_depth()

MDSRank::_dispatch()

|__若message不是从MDS发过来的,则直接返回

|__若MDS处于laggy状态

|__将message插入到waiting_for_nolaggy数组

|__若waiting_for_nolaggy数组不为空且此消息为新的消息

|__将message插入到waiting_for_nolaggy数组

|__handle_deferrable_message()                                        核心消息处理函数

|___advance_queues()                                                        核心消息处理函数

|__此时若MDS处于laggy状态,则直接返回

|__若MDS处于CLIENTREPLAY状态且replay_queue为空

|__若此时没有client request

|__clientreplay_done()

|__若此时MDS处于stopping状态

|__MDLog::trim()

|__stopping_done()

MDRank::handle_deferrable_message()

|__获取待处理消息的类型

|__MDS_PORT_CACHE

|__MDCache::dispatch()                    对于CACHE类型的消息,由MDCache负责分发处理

|__MDS_PORT_MIGRATOR

|__MDCache::migrator::dispatch()     对于是MIGRATOR类型的消息,由MDCache::migrator负责分发处理

|__CEPH_MSG_CLIENT_SESSION/CEPH_MSG_CLIENT_RECONNECT/CEPH_MSG_CLIENT_REQUEST

|__Server::dispatch()                         对于client session相关的消息,由Server负责分发处理

|__MSG_MDS_SLAVE_REQUEST

|__Server::dispatch()                          对于SLAVE相关的消息,由Server负责分发处理

|__MSG_MDS_HEARTBEAT

|__MDBalancer::proc_message()       对于HEARTBEAT相关的消息,由MDBalance负责处理

|__MSG_MDS_TABLE_REQUEST

|__若request的操作码<0,则说明请求client处理

|__get_table_client()                    从client table中找到对应的client

|__client->handle_request()          由MDSTableClient负责处理消息请求

|__若request的操作码>=0,则说明请求server处理

|__get_table_server()                    从server table中找到对应的server

|__server->handle_request()          由MDSTableServer负责处理消息请求

|__MSG_MDS_LOCK/MSG_MDS_INODEFILECAPS

|__Locker::dispatch()                         对于LOCK类型的消息,由Locker负责分发处理

|__CEPH_MSG_CLIENT_CAPS/CEPH_MSG_CLIENT_CAPRELEASE/CEPH_MSG_CLIENT_LEASE

|__Locker::dispatch()                         对于client caps相关的消息,由Locker负责分发处理

MDSRank::_advance_queues()

|__遍历finished_queue

|__finished_queue.front()->complete(0)          调用finished_queue中成员中的complete回调函数

|__heartbeat_reset()

|__遍历waiting_for_nolaggy

|__若waiting_for_nolaggy成员中的元素在有效的MDSMap中

|__handle_deferrable_message()               处理这些等待nolaggy的消息

MDSRank::heartbeat_reset()

|__若hb为空,则直接返回

|__g_ceph_context->get_heartbeat_map()->reset_timeout()          重置heartbeat定时器,避免MDS suicide

========================获取MDSRank类成员相关============================

MDSRank::get_metadata_pool()

|__MDSMap::get_metadata_pool()          返回MDRank类中MDSMap类实例对应的metadata pool

MDSRank::get_table_client()                    目前只有SNAP使用MDSTable功能,其它模块没有使用

|__根据输入参数判断,若参数是TABLE_SNAP则返回snapclient,否则返回null

MDSRank::get_table_server()                    目前只有SNAP使用MDSTable功能,其它模块没有使用

|__根据输入参数判断,若参数是TABLE_SNAP则返回snapserver,否则返回null

MDSRank::set_osd_epoch_barrier()

|__设置osd_epoch_barrier = e

MDSRank::get_laggy_until()

|__Beacon::get_laggy_until()                         实际上返回的是Beacon的laggy时间

MDSRank::is_daemon_stopping()

|__返回stopping的当前值

MDSRank::reqeust_state()

|__Beacon::set_want_state()                    设置Beacon的want state

|__Beacon::send()                                     Beacon将状态发送给Monitor

==========================MDSRank启动/重启相关=============================

MDSRank::suicide()

|__若suicide_hook不为空,则调用suicide_hook->complete(0)函数

MDSRank::respawn()

|__若respawn_hook不为空,则调用respawn_hook->complete(0)函数

MDSRank::damaged()

|__Beacon::set_want_state(STATE_DAMAGED)          设置Beacon的状态为DAMAGED

|__MonClient::flush_log()

|__Beacon::notify_health()

|__respawn()                                                                 重新启动到standby模式

MDSRank::damaged_unlocked()

|__damaged()

MDSRank::handle_write_error()

|__若error==-EBLACKLISTED

|__respawn()          重新启动MDS

|__若mds_action_on_write_error>=2

|__respawn()

|__若mds_action_on_write_error==1          默认行为

|__MDCache::force_readonly()

MDSRank::is_stale_message()

|__消息源来自MDS进程

|__消息源MDS进程在mdsmap中没有inst信息/mdsmap中的inst信息与消息所带的inst信息不一致/mdsmap中消息源MDS进程已经down了

|__若消息的类型是CEPH_MSG_MDS_MAP,则不认为是stale message

|__若消息的类型是MSG_MDS_CACHEEXPIRE且mdsmap中的inst信息与消息所带的inst信息一致,则不认为是stale message

|__否则,认为是stale message

|__消息源不是来自MDS进程,则不认为是stale message

=========================send message相关=====================================

MDSRank::send_message()

|__Connection::send_message()               调用Connection的send_message()函数发送消息

MDSRank::send_message_mds()

|__检查mdsmap中对端MDS是否是up状态,若不是则直接返回

|__对于对端MDS的MDSMap不是最新的

|__messenger->send_message()               将最新的MDSMap发送给对端MDS

|__peer_mdsmap_epoch[mds] = mdsmap->get_epoch()          更新对端MDSMap所拥有的epoch值

|__messenger->send_message()                    将消息发送给对端MDS

MDSRank::forward_message_mds()

|__对于消息类型是CEPH_MSG_CLIENT_REQUEST

|__messenger->send_message(MClientRequestForward())          将client发送过来的消息转发到目的MDS处

|__对于对端MDS的MDSMap不是最新的

|__messenger->send_message()               将最新的MDSMap发送给对端MDS

|__peer_mdsmap_epoch[mds] = mdsmap->get_epoch()          更新对端MDSMap所拥有的epoch值

|__messenger->send_message()                    将消息发送给对端MDS

MDSRank::send_message_client()

|__若session->connection不为空

|__session->connection->send_message()          发送消息到client端

|__若session->connection为空

|__session->reopen_out_queue.push_back()          将消息插入消息队列中等待connection重新建立完毕后再发送

============================ProgressThread线程相关==========================

MDSRank::ProgressThread::entry()               ProgressThread核心处理函数

|__若当前没有需要处理的内容

|__cond.Wait()

|__若stopping==true

|__退出核心处理函数

|__MDSRank::_advance_queues()

MDRank::ProgressThread::shutdown()

|__调用线程库函数join()

=========================MDSRank boot相关======================================

MDSRank::boot_start()                    作为类C_MDS_BootStart的回调函数

|__若返回值小于0(执行boot过程中有错误出现)

|__当前状态是STANDBY_REPLAY并且返回值是EAGAIN

|__respawn()

|__返回值是EINVAL或ENOENT

|__damaged()

|__返回值不是上述的情况

|__suicide()

|__判断当前所处的BootStep阶段

|__MDS_BOOT_INITIAL

|__MDCache::init_layouts()

|__创建MDSGatherBuilder类实例且设置下一个BootStep阶段为MDS_BOOT_ROOT

|__InoTable::set_rank()               设置InoTable的rank值

|__InoTable::load()                      加载InoTable

|__SessionMap::set_rank()          设置SessionMap的rank值

|__SessionMap::load()                加载SessionMap

|__MDLog::open()                         打开MDLog

|__SnapServer::set_rank()               设置SnapServer的rank值

|__SnapServer::load()                    加载SnapServer

|__MDSGatherBuilder::activate()

|__MDS_BOOT_ROOT                         打开或创建ROOT inode

|__创建MDSGatherBuilder类实例且设置下一个BootStep阶段为MDS_BOOT_PREPARE_LOG

|__MDCache::open_mydir_inode()          加载mydir的inode

|__当前处于Starting状态或者当前MDS节点是MDSMap的根节点

|__MDCache::open_root_inode()

|__当前不是处于Starting状态或者当前MDS节点不是MDSMap的根节点

|__MDCache::create_root_inode()

|__MDSGatherBuilder::activate()

|__MDS_BOOT_PREPARE_LOG

|__当前MDS处于replay状态

|__MDLog::replay()                         执行replay操作

|__当前MDS不是处于replay状态

|__MDLog::append()

|__starting_done()

|__MDS_BOOT_REPLAY_DONE

|__replay_done()

MDRank::starting_done()

|__request_state(STATE_ACTIVE)          设置当前状态为ACTIVE

|__MDCache::open_root()

|__MDLog::start_new_segment()

MDSRank::creating_done()

|__request_state(STATE_ACTIVE)

MDSRank::boot_create()

|__创建MDSGatherBuilder类实例且执行完毕后执行回调函数creating_done()

|__MDCache::init_layouts()

|__SnapServer::set_rank()

|__InoTable::set_rank()

|__SessionMap::set_rank()

|__MDLog::create()

|__MDLog::prepare_new_segment()

|__若MDS节点是MDSMap的根节点

|__MDCache::create_empty_hierarchy()

|__MDCache::create_mydir_hierarchy()

|__InoTable::reset()

|__InoTable::save()

|__SessionMap::save()

|__SnapServer::reset()

|__SnapServer::save()

|__MDLog::journal_segment_subtree_map()

|__MDLog::flush()

|__MDSGatherBuilder::activate()

=====================replay相关=============================

MDSRank::calc_recovery_set()

|__MDSMap::get_recovery_mds_set()          从MDSMap中获取到处于recovery状态的所有MDS节点

|__从recovery状态下的MDS节点中删除此MDS节点

|__MDCache::set_recovery_set()                    更新MDCache中的recovery_set值

MDSRank::replay_start()

|__设置standby_replaying=true

|__calc_recovery_set()

|__Objecter::wait_for_map()                         获取上次失败前最新的osdmap

|__boot_start()

MDSRank::_standby_replay_restart_finish()

|__若处于standby MDS的journal小于active MDS的journal的expire_pos

|__respawn()               重新启动MDS

|__若处于standby MDS的journal大于active MDS的journal的expire_pos

|__MDLog::standby_trim_segments()

|__boot_start(MDS_BOOT_PREPARE_LOG)          调用boot_start()函数进行replay操作

MDSRank::standby_replay_restart()

|__standby_replaying==true

|__MDLog::get_journaler()->reread_head_and_probe()     得到journal的head和probe信息后,执行回调函数_standby_replay_restart_finish

|__standby_replaying==false

|__Objecter::wait_for_map()                    获取上次失败前最新的osdmap

|__成功获取最新的osdmap

|__MDLog::get_journaler()->reread_head_and_probe()     得到journal的head和probe信息后,执行回调函数_standby_replay_restart_finish

MDSRank::replay_done()

|__若处于standby replay状态

|__设置定时器,当定时器超时后执行standby_replay_restart()

|__若此时正处于replaying(standby_replaying==true)

|__设置standby_replaying=false

|__standby_replay_restart()                         重新启动standby replay

|__若处于replay完成状态

|__journal read的位置应该和journal write的位置重合

|__设置MDS journal writable

|__SessionMap::save()                         保存SesionMap

|__InoTable::save()                                保存InoTable

|__若此时只有一个MDS

|__request_state(STATE_RECONNECT)     设置当前状态为RECONNECT

|__若此时有多个MDS

|__request_state(STATE_RESOVE)          设置当前状态为RESOLVE

==================resolve相关===========================

MDSRank::reopen_log()

|__MDCache::rollback_uncommitted_fragments()          在MDCache中回滚未提交的fragments

MDSRank::resolve_start()

|__reopen_log()

|__MDCache::resolve_start()                         调用MDSCache之行resolve,当之行完毕后调用回调函数resolve_done()

MDSSRank::resolve_done()

|__request_state(STATE_RECONNECT)               设置当前状态为RECONNECT

====================reconnect相关==========================

MDSRank::reconnect_start()

|__若last_state==STATE_REPLAY

|__reopen_log()

|__Server::reconnect_client()                              调用Server重新与client进行连接,连接成功后执行回调函数reconnect_done()

MDSRank::reconnect_done()

|__request_state(STATE_REJOIN)                    设置当前状态为REJOIN

=====================rejoin相关============================

MDSRank::rejoin_joint_start()

|__MDCache::rejoin_send_rejoins()

MDSRank::rejoin_start()

|__MDCache::rejoin_start()                              调用MDCache之行rejoin操作,之行完毕后执行回调函数rejoin_done()

MDSRank::rejoin_done()

|__MDCache::show_subtrees()/show_cache()

|__若replay_queue为空

|__request_state(STATE_ACTIVE)

|__若replay_queue不为空

|__request_state(STATE_CLIENTREPLAY)

=======================clientreplay相关==============================

MDSRank::clientreplay_start()

|__queue_one_replay()

MDSRank::queue_on_replay()

|__若replay_queue为空

|__若MDSCache::get_num_client_requests()==0

|__clientreplay_done()                              client replay完成

|__replay_queue不为空

|__queue_waiter()                         从replay_queue队列中取出一个请求待处理

MDSRank::clientreplay_done()

|__request_state(STATE_ACTIVE)

==========================active相关================================

MDSRank::active_start()

|__若last_state==STATE_CREATING

|__MDCache::open_root()

|__MDCache::clean_open_file_lists()

|__MDCache::export_remaining_imported_caps()

|__MDCache::reissue_all_caps()

==========================recovery相关==========================

MDSRank::recovery_done()

|__若MDSMap中的tableserver==whoami

|__从MDSMap中得到clientreplay/active/stopping状态下的MDS节点

|__SnapServer::finish_recovery()

|__MDSCache::start_recovered_truncates()

|__MDSCache::do_file_recover()

|__MDSCache::populate_mydir()

=======================stopping相关========================

MDSRank::stopping_start()

|__MDCache::shutdown_start()

MDSRank::stopping_done()

|__request_state(STATE_STOPPED)

=========================handle mdsmap相关==============================

MDSRankDispatcher::handle_mds_map(MMDSMap *m, MDSMap *oldmap)

|__得到MDS进程的当前状态oldstate = state

|__从MDSMap中得到最新的state

|__更新peer_mdsmap_epoch[] = epoch           更新对端mdsmap的epoch值

|__根据oldstate和state判断更新的状态是否有效

|__无效,则调用respawn()

|__Beacon::set_want_state(state)          更新Beacon的当前state值

|__之前的状态是recover,现在的状态是active或clientreplay

|__recovery_done()                              表示完成了recover

|__active状态

|__active_start()

|__replay状态

|__replay_start()

|__resolve状态

|__resolve_start()

|__reconnect状态

|__reconnect_start()

|__rejoin状态

|__rejoin_start()

|__clientreplay状态

|__clientreplay_start()

|__creating状态

|__boot_create()

|__starting状态

|__boot_start()

|__stopping状态

|__stopping_start()

|__oldmap不是resolving而mdsmap是resolving

|__MDSMap::get_mds_set(STATE_RESOLVE)

|__calc_recovery_set()

|__MDCache::send_resolves()

|__oldmap不是rejoining而mdsmap是rejoining

|__rejoin_joint_start()

|__oldstate>=STATE_REJOIN

|__从old mdsmap和new mdsmap中分别取出STATE_ACTIVE/STATE_CLIENTREPLAY/STATE_REJOIN的MDS

|__遍历new mdsmap中的这些MDS

|__MDS不在old mdsmap中                         新的MDS

|__MDCache::kick_recovers()

|__MDCache::kick_open_ino_peers()

|__oldstate>=STATE_CLIENTREPLAY

|__从old mdsmap和new mdsmap中分别取出STATE_ACTIVE/STATE_CLIENTREPLAY的MDS

|__遍历new mdsmap中的这些MDS

|__MDS不在old mdsmap中                         新的MDS

|__handle_mds_recovery()

|__从old mdsmap和new mdsmap中分别取出down的MDS

|__遍历new mdsmap中的这些MDS

|__MDS不在old mdsmap中                         新的down掉的MDS

|__Messenger::mark_down()

|__handle_mds_failure()

|__从new mdsmap中得到所有up状态的MDS

|__遍历new mdsmap中的这些MDS

|__在old mdsmap中存在但是inst内容不一致               新的MDS修改了inst

|__Messenger::mark_down()

|__handle_mds_failure()

|__从old mdsmap和new mdsmap中得到所有stopped状态的MDS

|__遍历new mdsmap中的这些MDS

|__在old mdsmap中不存在                             新的MDS stopped了

|__MDCache::migrator::handle_mds_failure_or_stop()

|__当前没有replay状态的MDS

|__MDBalancer::try_rebalance()

|__遍历waiting_for_mdsmap数组

|__唤醒该数组中所有成员

|__当前状态是active

|__set_osd_epoch_barrier()

|__MDCache::noteify_mdsmap_changed()

MDSRank::handle_mds_recovery()

|__MDCache::handle_mds_recovery()

|__SnapServer::handle_mds_recovery()

|__queue_waiter(waiting_for_active_peer[who])

MDSRank::handle_mds_failure()

|__MDCache::handle_mds_failure()

|__SnapClient::handle_mds_failure()

php mds函数,MDSRank类解析 - linux_hunter的个人页面 - OSCHINA - 中文开源技术交流社区...相关推荐

  1. java中加载窗口的函数_Java函数调用 - playgame的个人页面 - OSCHINA - 中文开源技术交流社区...

    Java函数调用和存储过程一样步骤如下: 1. 编写自定义的函数,或调用系统函数,为简单起见,我调用Mysql CONCAT()函数. 2.编写java调用测试类,可以是main方法,也可以JUnit ...

  2. linux fflush函数,fflush - wwliu的个人页面 - OSCHINA - 中文开源技术交流社区

    概述 函数名: fflush 功 能: 清除文件缓冲区,文件以写方式打开时将缓冲区内容写入文件 头文件: #include 原型:int fflush(FILE *stream) #include # ...

  3. java的异常解析_java异常解析 - liop的个人空间 - OSCHINA - 中文开源技术交流社区...

    抛出异常,捕捉异常,输出异常. /** * 自定义异常类 */ public class CustomerException extends RuntimeException { private St ...

  4. php 原理 淘口令 解密_淘口令解析 - super19911115的个人空间 - OSCHINA - 中文开源技术交流社区...

    淘口令解析 通过程序解析淘口令,无需联盟开发者权限,只需几行代码就可实现自动识别淘口令: def query_password(sign_server, share_password): data = ...

  5. java绘制统计直方图取平均_统计学——直方图解析 - osc_lv8qb16y的个人空间 - OSCHINA - 中文开源技术交流社区...

    直方图(Histogram),又称质量分布图,是一种统计报告图, 由一系列高度不等的纵向条纹或线段表示数据分布的情况. 一般用 横轴表示数据类型,纵轴表示分布情况. 直方图是数值数据分布的精确图形表示 ...

  6. 泊松分酒 java课件_泊松分酒原理 - 我类个擦的个人空间 - OSCHINA - 中文开源技术交流社区...

    有一个12品脱(pint)的酒瓶,里面装满葡萄酒,另有8品脱和5品脱的瓶子各一个.问如何从中分出6品脱的酒出来? 传说泊松年轻时成功解决了该问题,勾起了他对数学的兴趣而投身数学研究,因此该问题被称为泊 ...

  7. 三个瓶子分酒c语言源码,泊松分酒原理 - 我类个擦的个人空间 - OSCHINA - 中文开源技术交流社区...

    有一个12品脱(pint)的酒瓶,里面装满葡萄酒,另有8品脱和5品脱的瓶子各一个.问如何从中分出6品脱的酒出来? 传说泊松年轻时成功解决了该问题,勾起了他对数学的兴趣而投身数学研究,因此该问题被称为泊 ...

  8. java回调函数的生命_Java的回调函数 - choaklin 的个人空间 - OSCHINA - 中文开源技术交流社区...

    暂且不提回调函数的各种定义,如我本人,虽然知道JavaScript的回调的使用,但是百科了回调的定义,还是觉得云里来雾里去.所以大可先从已熟悉的入手,旁推侧引它的原理,再引出Java版的实现. 因为博 ...

  9. C语言调用自定义交换函,C语言函数篇 - personal page of Msingwen - OSCHINA - 中文开源技术交流社区...

    函数(一): 函数知识点 函数:能实现某种特定功能的代码 分为系统函数(内置函数) (例如printf scanf  getchar  putchar  time  ..) 和  自定义函数  两类! ...

最新文章

  1. 【Android 逆向】Android 中常用的 so 动态库 ( libdvm.so | libart.so | libandroid_runtime.so | libandroidfw.so )
  2. 作为本科大学生比较适合的水准比较好的,嵌入式软件系统的会议
  3. windows 10安装gensim、nltk
  4. C++ Primer 7.33 练习编写成员函数
  5. 怎样用php写入数据库表,PHP如何将数据写入到MYSQL数据库
  6. cocos2dx打飞机项目笔记二:BulletLayer类
  7. 笔记本电脑自带麦克风吗_想让声音变得好听吗,不花一分钱,让你的电脑拥有外置麦克风...
  8. 《云服务器》与《传统服务器》的区别
  9. 剑指offer(C++)-JZ77:按之字形顺序打印二叉树(数据结构-树)
  10. 开课吧:数据分析的价值体现在哪些方面?
  11. 第一节 MongoDB介绍及下载与安装
  12. 微信购物商城系统怎样吸引住客户,来转换为商城系统的粉丝?
  13. 北斗卫星定位系统原理
  14. 降雨量等值线图(一)——底图整饬
  15. PTA 乙级 1003 我要通过! (20 分) C++
  16. 云计算开发技术Python自动化运维开发实战二
  17. PCB布局和绘制的关键操作
  18. 曹翱,我永远爱你(FOR循环和WHILE循环讲解)
  19. android手机备份恢复出厂设置密码,手机恢复出厂设置 如何让安卓手机恢复出厂设置经验分享...
  20. ASO优化:为什么要做APP竞品分析

热门文章

  1. hive Cannot truncate non-managed table
  2. Unity 托管内存(Managed Memory)
  3. linux cpu 查看微码,intel cpu微码 intel官网下的cpu微码 - 下载 - 搜珍网
  4. Apollo星火计划学习笔记——Control 专项讲解(PID)
  5. Java医院预约挂号系统
  6. narwal机器人_中国黑科技扫地机器人云鲸NARWAL将强势回归国内市场
  7. ts定义数组类型_ts中类型
  8. 程序员的四个等级:菜鸟、普通、大牛、大神
  9. 苹果浏览器无法边下边播MP4(谷歌浏览器可以)
  10. oracle 数据库锁 lock mode 的几种类型