Comments (2)
實作登入次數自動增加機制的程式碼,根據以 PttBBS 原始碼為範圍、使用 ripgrep 所取得的字串搜尋結果,推測有兩處:
mbbsd/passwd.c
pwcuLoginSave()
——每日登入時增加一次(「登入時的次數增加」)- 次數增加條件:上一次增加登入次數的時間(
cuser.lastlogin
)在本次登入日 00:00 之前
- 次數增加條件:上一次增加登入次數的時間(
util/update_online.c
fastcheck()
——單次線上期間每超過一天增加一次(「線上期間的次數增加」)- 次數增加條件:每天某時間點時,使用者在線上且距離上一次增加登入次數的時間超過一天。這個時間會依站臺設定而異,在 Ptt 上是 04:00。
上述兩者在增加登入次數(cuser.numlogindays
)時,都會設定 cuser.lastlogin
為某個接近目前時間的時間值(「重設用目前時間值」)。
節錄自 util/update_online.c
的相關程式碼
Lines 14 to 16 in 7b35778
Lines 50 to 61 in 7b35778
Line 77 in 7b35778
線上使用者登入後,其線上期間的計算方式為 now_cond - cuser.lastlogin
,其中 now_cond
為「判斷用目前時間值」,而 cuser
為對應此使用者的 userec_t
物件。
以下程式碼會阻止線上期間未超過一天的使用者的登入次數增加:
Lines 50 to 51 in 7b35778
urec.lastlogin >= base
… (1) →
urec.lastlogin >= now_cond - DAY_SECONDS
(now_cond
為「判斷用目前時間值」)→
urec.lastlogin + DAY_SECONDS >= now_cond
→
now_cond <= urec.lastlogin + DAY_SECONDS
… (2)→
now_cond - urec.lastlogin <= DAY_SECONDS
→
duration <= DAY_SECONDS
(duration
為線上期間)
可知在 update_online
所算出的線上期間大於一天的情況下,才會增加該使用者的登入次數。
作為比較,這是 commit 05702e5 時的對應程式碼:
Lines 45 to 46 in 05702e5
上述 (2) 式與之相比多了等號。
根據前面討論所提到的「線上期間的次數增加」機制的描述,以及 update_online
是支單獨程式的事實,我推測 update_online
是透過 cron
每天定時執行一次的。
假設電腦執行速度快得使「重設用目前時間值」(在上述節錄內容內,行號為 77 之行)與「判斷用目前時間值」(在上述節錄內容內,行號為 16 之行)皆相同。(因為參考 util/update_online.c
與其所使用的 common/bbs/cache.c
中的函式的定義,在程式執行流程中的上述兩行程式碼間不存在固定的延時,所以如果電腦執行速度相當快的話,這兩行可視為同時執行)
情況一
如果 cron
某次執行 update_online
時延遲,導致所取得的「重設用目前時間值」比預期延後超過一秒,這個情況下如果下次執行時所取得的時間值與預期相比沒有延後,那麼本次登入後已被 update_online
增加過登入次數且仍在線上的使用者,將會因為所算出的線上期間小於一天,所以其登入次數不會增加,造成少算的狀況。
一種解決方法是重新引入時間判斷的誤差容許值,但在定時執行未出現延遲時會導致允許將線上期間未超過一天的使用者的登入次數增加。
另一種解決方法是將「重設用目前時間值」與「判斷用目前時間值」取為最近的分鐘或小時的開始時間。
又另一種解決方法請見情況四。
假設電腦執行速度快,cron
每天皆一秒不差地定時執行一次 update_online
,使得其執行時間的值、「重設用目前時間值」、與「判斷用目前時間值」皆相同。
情況二
如果使用者被過去最近一次 update_online
的每天定時執行增加了登入次數,或如果使用者本次登入後未被 update_online
增加過登入次數,並且使用者登入的時間點為過去最近一次 update_online
執行時所取得的「判斷用目前時間值」的時間點,那麼下一次執行時,這個使用者的線上期間將會等於一天,所以其登入次數不會增加,造成少算的狀況。遇到下二次執行時才會增加,但僅增加一次。
修正方法是移除上述 (1) 式中的等號。
情況三
如果使用者本次登入後未被 update_online
增加過登入次數,並且使用者登入的時間點比過去最近一次 update_online
執行時所取得的「判斷用目前時間值」的時間點還晚超過一秒後登入,那麼這個使用者的線上期間達到大於等於一天的時間會落在下一次到下二次遇到 update_online
每天定時執行之間。這個情況下,如果這個使用者在下二次遇到 update_online
的每天定時執行前離線,將會因為 update_online
不處理離線使用者而不增加其登入次數而造成少算的狀況。
一種解決方法是在使用者登出時會執行的處理函式(例如 pwcuExitSave()
)中,加上以下處理邏輯:
如果以
cuser.lastlogin - now
算出的線上期間大於等於一天則增加一次登入次數(「離線時的次數增加」)。
但在使用者的對應處理程序異常終止執行而導致「離線時的次數增加」機制未被執行的情況下,還是會造成少算的狀況。
情況四
以下是虛構的說明範例:
- 使用者甲在某天 03:59:59 登入,在後天 04:00:01 登出,在線上共 48 時 0 分 2 秒
- 登入次數增加時間點:第一天 03:59:59、第二天 04:00:00、第三天 04:00:00,共三次
- 使用者乙在某天 04:00:01 登入,在後天 04:00:03 登出,在線上共 48 時 0 分 2 秒
- 登入次數增加時間點:第一天 04:00:01、第三天 04:00:00,共兩次
可見使用者甲與乙的線上期間相同,僅有登入與登出的時間有些許前後差別,但乙的登入次數卻少算了一次。
一種解決方法是將「重設用目前時間值」取為 cuser.lastlogin + DAY_SECONDS
以保留實際線上期間的資訊,並搭配使用情況三的解決方法處理離線時的線上期間。
使用此解決方法後的上述說明範例:
- 使用者甲在某天 03:59:59 登入,在後天 04:00:01 登出,在線上共 48 時 0 分 2 秒
- 登入次數增加時間點:第一天 03:59:59(登入)、第二天 04:00:00(線上;尚有 1 秒未計)、第三天 04:00:00(線上;尚有 1 秒未計),共三次
- 使用者乙在某天 04:00:01 登入,在後天 04:00:03 登出,在線上共 48 時 0 分 2 秒
- 登入次數增加時間點:第一天 04:00:01(登入)、第三天 04:00:00(線上;尚有 23 時 59 分 59 秒未計)、第三天 04:00:03(登出;尚有 2 秒未計),共三次
from pttbbs.
Related Issues (20)
- whence in PttLock should be SEEK_SET? (or PttLock after lseek should set offset as 0?) HOT 4
- 請問如何找回ID和密碼 HOT 5
- Some articles in the searching result for the word "初音" are missing in board C_Chat HOT 1
- [Feature Request] Support more than 8 characters password HOT 10
- 可用單一信箱多次認證 HOT 2
- Split out common code for deleting users
- Use ngx.exit(444)
- Add SO_REUSEPORT support to logind HOT 1
- User ID rename does not update regemaildb
- Email input length hardcoded HOT 1
- [Bug] Ptt web search logic error HOT 2
- logind compile error HOT 2
- 使用 Mac 連上 term.ptt.cc,在發表文章/發送站內信時按下 ^ + X 沒有任何反應 HOT 4
- 看板下面的 bar 在特定情況下會消失
- [propose] Replace .PASSWDS with DB (mongodb) HOT 6
- BRD_WARNEL 的註解有錯
- Possible one more i++ in cmsys.strip_nonebig5? HOT 1
- 關於 SHM 沒有加上 volatile 這件事 HOT 10
- [資訊] 如果你收不到認證信的話 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pttbbs.