2016年6月26日 星期日

NAT64 和 DNS 64

參考資料

IPv4 要用完了 (喊了十幾年, 最近是玩真的了), 在骨幹和 server 都轉成 IPv6 的過渡期, 用戶端也要轉換, 不然 server 是轉心酸的。但是大量 server 還是用 IPv4, 所以要讓 client 能同時支援 IPv4 和 IPv6才行。

如果你是網管, 希望讓用戶可以同時連 IPv4 和 IPv6 的位置, 一個可能的作法是建置「純 IPv6 環境」, 永遠拿到 IPv6 位置, 永遠連 IPv6 的位置。但要讓 IPv6 client 也能連 IPv4 位置, 需要 NAT64+DNS64 幫忙處理。

原理是 DNS64 會同時查 IPv6 和 IPv4 的位置, 有 IPv6 就用 IPv6, 沒有就轉換 IPv4 為 IPv6, prefix 配合 NAT64 的設定, 讓 client 連往該 IP 的封包會先經過 NAT64 router。第二份 slide 有詳細的流程圖。

然後 NAT64 會再轉換 IPv6 的封包成 IPv4 出去, 無縫接上用 IPv4 位置的 server。至於 client 收到 DNS64 回應的正常 IPv6 位置, 就透過一般 router 直接出去, 不用經過 NAT 64。

對設計後端 server 的人來說, 有愈多用戶可以連 IPv6 位置, 有愈高的機會考慮用 IPv6 位置。

對 app 開發者來說, 了解有些用戶的網路環境會用 DNS64+NAT64 的配置, 所以要用 domain name 連上自家 server, 這樣自家 server 用 IPv4 或 IPv6 都會通。

2016年4月16日 星期六

查詢 Web 標準是否有支援

備忘待補更多來源:

如何 git merge 更改檔名的檔案

參考資料:

如果在 branch 裡有 rename file X 為 Y, 並且 master 和 branch 都有改 X ( Y ) 的內容。那麼, merge master 的時候, git 可能會回報 master 的 X 被刪除了, 造成 merge conflict (deleted in ... and modified in ...)。

解法是提高 merge.renameLimit, 比方說 git config merge.renameLimit 999999999。merge 時間會久一點, 但 git 會找出 X 在 branch 裡已被 rename 成 Y。

用 vimdiff 作 git merge

參考文章

以前我用 kdiff3, 後來需要在 terminal merge, 改試 vimdiff, 也很好用。

設定:

$ git config --global merge.tool vimdiff

執行 (在 git merge 有 unsolved conflict 後):

$ git mergetool

UI 顯示:

  • 左上: LOCAL
  • 中上: BASE
  • 右上: REMOTE
  • 下面: 編輯區

vim 指令:

  • [c, ]c: 在 hunk 間移動, 和 vim-gitgutter 一樣
  • 搜 "<<<<" 找 conflict
  • :diffget LOCAL: 目前的 hunk 選用 LOCAL
  • :diffget REMOTE: 目前的 hunk 選用 REMOTE
  • :diffupdate: 更新 diff 畫面

修改後存檔離開, 會自動 resolved conflict。無修改離開會跳過 merge, 維持原本狀態。

其它

查看 merge 狀態:

$ git status

如果整份檔案都要選用 LOCAL, 改用 git 指令:

$ git checkout --ours

全用 REMOTE:

$ git checkout --theirs

2016年1月10日 星期日

2015年11月21日 星期六

multiple thread 存取共享資料的小技巧

最近看到不錯的寫法, 備忘一下。

通常我們不希望 main thread 被 block [*1], 所以會另外開 worker thread 處理耗 CPU 的工作。主要的需求是避免 block main thread, 其次是縮短完成工作的時間。

由於 main thread 和 worker thread 需要互相傳遞一些資料, 有可能造成 race condition, 導致程式行為有時不正確或是掛掉。這裡討論幾種避免 race condition 的作法。

用一個 "global" lock 保護整個 thread 的資料

worker thread 全部函式都用同一個 lock 保護。

  • 優點: 容易實作。
  • 缺點: main thread 在 worker thread 忙的時候存取共享資料, 還是會被 worker thread block。

不同群共享的資料用不同的 lock 保護

和上個作法類似, 不過資料分群用不同 lock 保護。

  • 優點: 減少 main thread 被 block 的機會。
  • 缺點: 實作有些複雜, 可能會漏保護到新加的變數。並且 main thread 仍有可能被 block。

避免共享資料

如果資料只有一個 thread 會用到, 就直接轉交給另一個 thread (改變 ownership)。若兩個 thread 都會用到, 先複製一份再轉交給另一個 thread。沒有共享的資料, 就不需用 lock 保護了 (但仍需透過 message loop 或 queue 傳遞資料到另一個 thread)。

  • 優點: 複製的時間不長, 且可以掌控占據 main thread 的時間, 完全不受 worker thread 影響
  • 缺點: 需要仔細設計複製和傳遞資料的機製, 確保沒有共享資料。

需要同步資料的時候, 記得只能允許一個方向的 block。比方說 main thread 可以透過 conditional variable 來 block worker thread, 但不允許反過來的操作, 這樣就不會有 dead lock。

不用 lock 的注意事項

每個函式都要放 assert 確保函式在正確的 thread 執行。若一個 class 有兩份資料分別在兩個 thread 下執行的話, 可以考慮訂兩個 struct, 比方說 MainData 和 WorkerData, 然後透過 private method 存取資料, 藉此確保 thread safe:

// C++
class MyClass
{
public:
   ...

private:
  MainData& GetMainData();
  WorkerData& GetWorkerData();

  struct MainData {
    ...
  };
  struct WorkerData {
    ...
  };
  MainData m_mainData;
  WorkerData m_workerData;
};

MainData& MyClass::GetMainData()
{
  assert(InMainThread());
  return m_mainData;
}

WorkerData& MyClass::GetWorkerData()
{
  assert(InWorkerThread());
  return m_workerData;
}

這樣程式寫錯時會造成 assert failed, 可以很快地修正。

備註

*1 比方說 daemon 的 main thread 會不斷收新的連線, GUI 的 main thread 會收使用者的輸入。main thread 被 block 而沒有反應的話, 使用者會覺得軟體有問題。

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...