Feeds:
文章
迴響

Archive for the ‘程式設計’ Category

環境

  1. Windows 10
  2. TDM-GCC x64 5.1.0
  3. CMake 3.8
  4. Python 2.7.7

注意

  1. sh.exe 不能在 PATH 環境變數中被找到, 如果安裝 Git 記得編譯前將路徑從 PATH 中移除
  2. gcc, cmake, python 所在路徑加到 PATH 環境變數

編譯

git clone https://github.com/BYVoid/OpenCC.git
cd OpenCC
cmake -H. -Bbuild -G "MinGW Makefiles" 
cmake --build build --config Release 

編譯結果

/build/src
    * libopencc.dll
    * libopencc.dll.a
    * Opencc_Export.h
    * /tools
        * libopencc.dll
        * opencc.exe
        * opencc_dict.exe
        * opencc_phrase_extract.exe
/data/config/*.json -- 配置檔

Read Full Post »

測著測著就來到 1.0 正式版.. 這算是目前測過比較完整的官方範例, 包含後端的網路建立(Peer*3, Orderer*1, CA*2), ChainCode *1, 前端的 Fabric-sdk-node 呼叫測試

快速建立後端網路

  1. 下載 https://github.com/hyperledger/fabric-samples/tree/master/balance-transfer
  2. 調整 artifacts/docker-compose.yaml 的 volumes 對應
  3. docker-compose -f docker-compose.yaml up -d

網路初始的容器狀態

建立 fabric-sdk-node 容器

  1. docker pull node:6.9.0
    • 官方說法目前不支援 7.x, 8.x
  2. 修改 balance-transfer/config.json 和 balance-transfer/app/network-config.json 的 localhost 成 docker mahcine ip
    • docker machine ip 可用 docker-machine ip 取得
  3. docker run -it –name fsn -v /host/balance-transfer:/code node:6.9.0 bash
  4. mkdir -p /tmp/app
  5. cp -r /code/. /tmp/app
    • 因為直接在 volume 映射目錄初始化會出現建立 soft link 失敗
  6. cd /tmp/app
  7. npm install
  8. node app.js
    • 啟動 express web server, port 4000

測試 REST API

  • docker exec -it fan bash
    • 進入 node 容器

      取得 Token

curl -s -X POST \
    http://localhost:4000/users \
    -H "content-type: application/x-www-form-urlencoded" \
    -d 'username=Jim&orgName=org1'

記下 token (有時效性, 過期重取) “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA"

建立 channel

  • channel 名稱 “mychannel"
curl -s -X POST \
  http://localhost:4000/channels \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json" \
  -d '{
    "channelName":"mychannel",
    "channelConfigPath":"../artifacts/channel/mychannel.tx"
}'

加入 channel

curl -s -X POST \
  http://localhost:4000/channels/mychannel/peers \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json" \
  -d '{
    "peers": ["192.168.99.100:7051","192.168.99.100:7056"]
}'

安裝 chaincode

curl -s -X POST \
  http://localhost:4000/chaincodes \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json" \
  -d '{
    "peers": ["192.168.99.100:7051","192.168.99.100:7056"],
    "chaincodeName":"mycc",
    "chaincodePath":"github.com/example_cc",
    "chaincodeVersion":"v0"
}'

啟用

curl -s -X POST \
  http://localhost:4000/channels/mychannel/chaincodes \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json" \
  -d '{
    "peers": ["192.168.99.100:7051"],
    "chaincodeName":"mycc",
    "chaincodeVersion":"v0",
    "functionName":"init",
    "args":["a","100","b","200"]
}'

Invoke request

curl -s -X POST \
  http://localhost:4000/channels/mychannel/chaincodes/mycc \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json" \
  -d '{
    "peers": ["192.168.99.100:7051", "192.168.99.100:7056"],
    "fcn":"move",
    "args":["a","b","10"]
}'

Chaincode Query

curl -s -X GET \
  "http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer1&fcn=query&args=%5B%22a%22%5D" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

使用區塊編號查詢區塊資訊

  • /blocks/BlockID
curl -s -X GET \
  "http://localhost:4000/channels/mychannel/blocks/1?peer=peer1" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

使用 TransactionID 查詢交易

  • transactions/TxID
    • TxID 可透過 invoke chaincode 返回值取得也可透過
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/bb6c007aa035cf9eb29154e6e3d90fb752d3e853adbc49c84d68385482b184be?peer=peer1 \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

Query ChainInfo

curl -s -X GET \
  "http://localhost:4000/channels/mychannel?peer=peer1" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

Query Installed chaincodes

curl -s -X GET \
  "http://localhost:4000/chaincodes?peer=peer1&type=installed" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

Query Instantiated chaincodes

curl -s -X GET \
  "http://localhost:4000/chaincodes?peer=peer1&type=instantiated" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

Query Channels

curl -s -X GET \
  "http://localhost:4000/channels?peer=peer1" \
  -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTk4NTUwMzcsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTk4MTkwMzd9.McFgn4pABM_uqv2vtVbU5SaLWy43OO-q_DkCsEOfcxA" \
  -H "content-type: application/json"

Read Full Post »

上次才剛玩 beta1 今天他就已經變成 RC1, 立馬更新繼續測試…

 

測試環境

  • Windows 7 x64
  • Docker 17.05.0-ce
  • VirtualBox 5.1.6
  • git 2.9.2(curl.exe, bash.ex)
  • bootstrap-1.0.0-rc1.sh

目錄結構

  • c:\docker
    • /fabric-samples
      • /bin
      • /basic-network
      • /chaincode-docker-devmode
      • /fabcar
      • /first-network

VirtualBox 共享目錄對應

  • /host : C:\docker

環境初始化

c:
cd docker
git clone https://github.com/hyperledger/fabric-samples.git
cd fabric-samples
curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap-1.0.0-rc1.sh | bash
curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/windows-amd64-1.0.0-rc1/hyperledger-fabric-windows-amd64-1.0.0-rc1.tar.gz | tar xz

初始化完成必要的 image

修改 *.yaml 的 volumes

  • 調整對應到 /host/fabric-samples 路徑

範例: chaincode-docker-devmode

Console1: 啟動服務

cd c:\docker\fabric-samples\chaincode-docker-devmode docker-compose -f docker-compose-simple.yaml up

Console2: 編譯/執行 ChainCode

  • 也可先用 go test 執行測試
docker exec -it chaincode bash
cd chaincode_example02
go build
CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./chaincode_example02

執行結果

Console3: 使用 ChainCode

docker exec -it cli bash

peer chaincode install -p chaincodedev/chaincode/chaincode_example02 -n mycc -v 0

peer chaincode instantiate -n mycc -v 0 -c ‘{“Args":[“init","a","100″,"b","200″]}’ -C myc

instantiate

peer chaincode invoke -n mycc -c ‘{“Args":[“invoke","a","b","10″]}’ -C myc

invoke

peer chaincode query -n mycc -c ‘{“Args":[“query","a"]}’ -C myc

query

程式更新

  • 版號更新為 ‘1.1’ (string, 每次異動都要不同)

CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:1.1 ./chaincode_example02

跑完全部流程應該會看到這個

peer chaincode install -p chaincodedev/chaincode/chaincode_example02 -n mycc -v 1.1

peer chaincode upgrade -C myc -n mycc -v 4 -c ‘{“Args":[“init","a", “10″, “b","20″]}’

peer chaincode invoke -C myc -n mycc -c ‘{“Args":[“create","arick"]}’

peer chaincode query -n mycc -c ‘{“Args":[“query","arick"]}’ -C myc

參考資料

Read Full Post »

這陣子支援了一個案子評估 ossim 可行性, 其中 ossim-agent 負責解析 Log 字串並拆解成 ossim 統一格式, 原先以為處理得這麼即時是透過 linux 的 inotify 機制, 後來細看原始碼才發現其實沒這麼複雜, 就是

1. 開檔

2. 指標移到檔尾

3. 即時取得一行 Log

4. 沒有資料? 檢查 inode 是否異動(可能被 logrotate 給換檔)

4.1 inode 異動就重新執行步驟 1 和 2

4.2 休息一下

5. 重複 1-4

其實 tail -f 也是這麼做. 其實蠻多地方都可以用到這各技巧. 不一定非得用 inotify, 而且檔案頻繁異動時 inotify 是否效率比較好還有待評估..

Read Full Post »

Kotlin 練習: FileViewer

一個簡單的命令列檔案檢視器. 可以文字/十進位/十六進位顯示內容.

原始碼: FileViewer.kt

編譯

kotlinc FileViewer.kt -include-runtime -d FileViewer.jar

執行

java -jar FileViewer.jar -h FileViewer.kt

結果

Read Full Post »

今天我就把 byte array 用 strncpy 複製…. 想說怎麼有時候會失敗. 萬惡的 \0 啊…

 

Read Full Post »

Code: https://github.com/mongodb/mongo-php-driver/blob/4b49b1ad80a300000cc7beab927ea43bdc6673fb/php_phongo.c

 

// 模組初始化
PHP_GINIT_FUNCTION(mongodb)
{
    // 初始化 hash
    zend_hash_init_ex(&mongodb_globals->clients, 0, NULL, php_phongo_client_dtor, 1, 0);
}

static void php_phongo_client_dtor(zval *zv)
{
   // http://mongoc.org/libmongoc/1.4.0/mongoc_client_destroy.html
   // Release all resources associated with client and free the structure.
    mongoc_client_destroy((mongoc_client_t *) Z_PTR_P(zv));
}

// Manager 初始化
void phongo_manager_init(php_phongo_manager_t *manager, const char *uri_string, zval *options, zval *driverOptions TSRMLS_DC) /* {{{ */
{
    mongoc_client_t  *client_ptr;

   // 產生hash
    hash = php_phongo_manager_make_client_hash(uri_string, options, driverOptions, &hash_len TSRMLS_CC)
   
   // 找尋 hash 吻合的連線, 吻合返回快取
    if ((client_ptr = zend_hash_str_find_ptr(&MONGODB_G(clients), hash, hash_len)) != NULL) {
        manager->client = client_ptr;
        goto cleanup;
    }
   
   // 建立新的 client
    manager->client = php_phongo_make_mongo_client(uri, ssl_opt TSRMLS_CC);
   
   // 更新 hash
    zend_hash_str_update_ptr(&MONGODB_G(clients), hash, hash_len, manager->client);

}

// 模組卸載
PHP_MSHUTDOWN_FUNCTION(mongodb)
{
   // 釋放所有的連線 
   // 觸發 php_phongo_client_dtor()
    zend_hash_destroy(&MONGODB_G(clients));
   
    mongoc_cleanup();

    return SUCCESS;
}

Read Full Post »

Older Posts »