ARST打卡第139周[139/521]

Algorithm

lc390_消除游戏

模拟,或者找规律,应该是找规律

模拟找规律: 巧妙利用每次左边界跳动的值。处理好数组中还剩的数组数,以及相邻数之差
https://leetcode-cn.com/problems/elimination-game/solution/xiao-chu-you-xi-by-leetcode-solution-ydpb/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int lastRemaining(int n) {
int a1 = 1;
int k = 0, cnt = n, step = 1;
while (cnt > 1) {
if (k % 2 == 0) { // 正向
a1 = a1 + step;
} else { // 反向
a1 = (cnt % 2 == 0) ? a1 : a1 + step;
}
k++;
cnt = cnt >> 1;
step = step << 1;
}
return a1;
}
};

Review

raft选举和提交动画

http://thesecretlivesofdata.com/raft/

生动有趣得讲述了raft协议

Tips

SO_REUSEADDR的使用

Share-vsftpd的vsf_two_process_start源码分析

common

父子进程之间通过priv_sock_login.h 中定义的模块来进行通信,然后进行处理

子进程

  • 所以进入vsf_two_process_start(&the_session);

  • 子进程处理一些命令,然后等待检测父进程那边是否登录成功,成功则退出,或者ssl_slave

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    void
    vsf_two_process_login(struct vsf_session* p_sess,
    const struct mystr* p_pass_str)
    {
    char result;
    priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_LOGIN);
    priv_sock_send_str(p_sess->child_fd, &p_sess->user_str);
    priv_sock_send_str(p_sess->child_fd, p_pass_str);
    priv_sock_send_int(p_sess->child_fd, p_sess->control_use_ssl);
    priv_sock_send_int(p_sess->child_fd, p_sess->data_use_ssl);
    result = priv_sock_get_result(p_sess->child_fd);
    if (result == PRIV_SOCK_RESULT_OK)
    {
    /* Miracle. We don't emit the success message here. That is left to
    * process_post_login().
    * Exit normally, unless we are remaining as the SSL read / write child.
    */
    if (!p_sess->control_use_ssl)
    {
    vsf_sysutil_exit(0);
    }
    else
    {
    ssl_slave(p_sess);
    }
    /* NOTREACHED */
    }
    // ...
    }
  • 父进程登录成功之后,就数据传输

父进程process_login_req

父进程进行while处理登录尝试

1
2
3
4
5
/* Parent - go into pre-login parent process mode */
while (1)
{
process_login_req(p_sess);
}

然后从父子进程socket上的父fd读取子进程那边传来的ACCT,PASS等等信息,然后进行登录处理

1
2
3
4
cmd = priv_sock_get_cmd(p_sess->parent_fd);
priv_sock_get_str(p_sess->parent_fd, &p_sess->user_str);
priv_sock_get_str(p_sess->parent_fd, &password_str);
e_login_result = vsf_privop_do_login(p_sess, &password_str);

其中 common_do_login中的第一句就是给子进程发送一个登录成功的信息,让子进程进入下一个阶段

并且如果是没有使用ssl,则等待子进程退出,否则就是ssl_slave

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void
common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
int do_chroot, int anon)
{
int was_anon = anon;
const struct mystr* p_orig_user_str = p_user_str;
int newpid;
vsf_sysutil_install_null_sighandler(kVSFSysUtilSigCHLD);
/* Tells the pre-login child all is OK (it may exit in response) */
priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
if (!p_sess->control_use_ssl)
{
(void) vsf_sysutil_wait();
}
else
{
p_sess->ssl_slave_active = 1;
}
// ...
}