Danilo Chang's Home Page
今天測試,發現可以改回來,所以回復原來的位址了。
我也同步更新了訊息在 comp.lang.tcl 上。
2016-01-18
2016-01-12
總之,被我弄到掛掉了
Danilo Chang's Home Page
受到 Google Sites 的影響,我目前無法編輯 tcl-lmdb 網頁,原因不明。我在實驗的過程中沒注意到 Google Sites 的刪除與複製網站功能有次數限制, 所以目前無法還原,就先目前這個網頁吧,如果可以改回來我再還原。
我在 comp.lang.tcl 也發了一篇文章 (Tcl-lmdb v0.3, Tclunqlite and Tcljsonnet),所以暫時就這樣了。
PS.
基本上我還是很介意,因為一個 Google Sites 的網站管理者無法編輯修改自己的網頁是一件很瞎的事情,到底是哪裡出問題了?
PS.
原來的 tcl-lmdb 無法修改內容,只能夠使用附件管理的方式來增加與刪除附件。 經過思考,我找到了一個解法。首先建立一個 test 網頁,而後將舊的 tcl-lmdb 網頁放在 test 網頁下,複製內容到新的 tcl-lmdb 網頁,於是就可以有一個可以修改的 tcl-lmdb 網頁。 我不確定這是不是 Google Sites 的 bug,但是看來 Google 的雲端服務可能沒那麼可靠。
不過我已經在 Github 也放了相關的 source code 內容,接下來如果 domain name 可以恢復,應該就可以解決這件事情了,只是日常使用就會遇到使用障礙,如果連 Google 都是如此,我會對整個雲端產業抱持著質疑的態度。
受到 Google Sites 的影響,我目前無法編輯 tcl-lmdb 網頁,原因不明。我在實驗的過程中沒注意到 Google Sites 的刪除與複製網站功能有次數限制, 所以目前無法還原,就先目前這個網頁吧,如果可以改回來我再還原。
我在 comp.lang.tcl 也發了一篇文章 (Tcl-lmdb v0.3, Tclunqlite and Tcljsonnet),所以暫時就這樣了。
PS.
基本上我還是很介意,因為一個 Google Sites 的網站管理者無法編輯修改自己的網頁是一件很瞎的事情,到底是哪裡出問題了?
PS.
原來的 tcl-lmdb 無法修改內容,只能夠使用附件管理的方式來增加與刪除附件。 經過思考,我找到了一個解法。首先建立一個 test 網頁,而後將舊的 tcl-lmdb 網頁放在 test 網頁下,複製內容到新的 tcl-lmdb 網頁,於是就可以有一個可以修改的 tcl-lmdb 網頁。 我不確定這是不是 Google Sites 的 bug,但是看來 Google 的雲端服務可能沒那麼可靠。
不過我已經在 Github 也放了相關的 source code 內容,接下來如果 domain name 可以恢復,應該就可以解決這件事情了,只是日常使用就會遇到使用障礙,如果連 Google 都是如此,我會對整個雲端產業抱持著質疑的態度。
2016-01-11
Convert Feedly.opml to SQLite3 database
目標是把 export 出來的 feedly.opml 檔案的資料放到 SQLite3 database 檔案。我寫完以後,才覺得…… 我好像多此一舉了。
第二個則是讀出來確定有轉存成功:
#!/usr/bin/tclsh
package require tdom
package require tdbc::sqlite3
# prepare our sqlite database
tdbc::sqlite3::connection create db "feedly.db"
set statement [db prepare {drop table if exists mylist}]
$statement execute
$statement close
set statement [db prepare {create table mylist (title TEXT, xmlUrl TEXT, htmlUrl TEXT, PRIMARY KEY (title))}]
$statement execute
$statement close
# setup feedly opml file path
set filename "/home/danilo/Personal/feedly.opml"
# parse XML data
set doc [dom parse [tDOM::xmlReadFile $filename "UTF-8"]]
set root [$doc documentElement]
set nodeList [$root selectNodes /opml/body/outline/outline]
set title ""
set xmlUrl ""
set htmlUrl ""
set statement [db prepare {insert into mylist values(:title, :xmlUrl, :htmlUrl)}]
foreach node $nodeList {
if {[catch {set title [$node getAttribute title]}] != 0} {
set title ""
}
if {[catch {set xmlUrl [$node getAttribute xmlUrl]}] != 0} {
set xmlUrl ""
}
if {[catch {set htmlUrl [$node getAttribute htmlUrl]}] != 0} {
set htmlUrl ""
}
$statement execute
}
$statement close
db close
第二個則是讀出來確定有轉存成功:
#!/usr/bin/tclsh
package require tdbc::sqlite3
tdbc::sqlite3::connection create db "feedly.db"
set statement [db prepare {SELECT * FROM mylist}]
$statement foreach row {
puts "RSS title: [dict get $row title]"
puts "RSS xmlUrl: [dict get $row xmlUrl]"
puts "RSS htmlUrl: [dict get $row htmlUrl]"
}
$statement close
db close
2016-01-08
SQLite 與 PostgreSQL 釋出新版本
2016-01-02
Update couchdbtcl and solr4tcl
couchdbtcl -
在寫 solr4tcl 的時候,我才注意到,我沒有在 couchdbtcl 中處理 http::geturl 連線失敗的情況(其實也只是加 catch,避免直接吐出來錯誤訊息),所以加進來處理的部份。
solr4tcl -
在進行更多測試的時候,我發現 ping method 雖然拿到 ok,但是我填的 URL 不是正確的,所以更新了 URL。然後 ping method 的 method 是 HEAD,看起來不用設定什麼 Accept header,我也更正了這部份。
在寫 solr4tcl 的時候,我才注意到,我沒有在 couchdbtcl 中處理 http::geturl 連線失敗的情況(其實也只是加 catch,避免直接吐出來錯誤訊息),所以加進來處理的部份。
solr4tcl -
在進行更多測試的時候,我發現 ping method 雖然拿到 ok,但是我填的 URL 不是正確的,所以更新了 URL。然後 ping method 的 method 是 HEAD,看起來不用設定什麼 Accept header,我也更正了這部份。
2015-12-29
solr4tcl v0.1: A lightweight Tcl client interface to Apache Solr
Homepage
solr4tcl
About
A lightweight Tcl client interface to Apache Solr. The library consists of a single Tcl Module file.solr4tcl is using Tcl built-in package http to send request to Aapache Solr.
This library requires package tdom.
Interface
The library has 1 TclOO class, Solr_Request.Provide below things:
- A simple search interface
- A simple interface to add, delete and update documents to the index (using XML Formatted Index Updates)
- Uploading file data by using Apache Tika
一些說明
經過閱讀 Apache Solr 的文件以後,使用 Tcl http package 送出 request 並且得到結果的記錄。應該是 work 的,起碼沒有出現網頁找不到或者是錯誤回應。
更新 2016/01/02:
雖然都是傳回 OK,但是 ping method 填的參數不是完全正確,我試著更新一份正確的。
2015-12-28
Apache Solr test code
solr4tcl-0.1.tm
Test code:
Apache Solr 沒有像 Apache CouchDB 一樣,有將 REST API 做一個整理表,所以我只是對 search 的部份做一個簡單的 search method,然後確定有正確的回應回來(而不是無法連線,或者是傳回來一個網頁不存在的 404 錯誤網頁,如果有執行 Solr 的 Solr Quick Start)。
更新 2015/12/29:
加入上傳檔案和 index 處理的部份
更新 2016/01/02:
更新 method ping 的參數
# solr4tcl --
#
package require Tcl 8.6
package require TclOO
package require http
package require tdom
package provide solr4tcl 0.1
#
# Solr_Request class: handle send request to Apache Solr
#
oo::class create Solr_Request {
variable server
variable path
variable solr_writer
constructor {SERVER} {
set server $SERVER
set path ""
set solr_writer "xml"
}
destructor {
}
method setDocumentPath {PATH} {
set path $PATH
}
#
# support type: xml, json and cvs
#
method setSolrWriter {WRITER} {
set solr_writer $WRITER
}
method send_request {url method {headers ""} {data ""}} {
variable tok
if {[string length $data] < 1} {
if {[catch {set tok [http::geturl $url -method $method \
-headers $headers]}]} {
return "error"
}
} else {
if {[catch {set tok [http::geturl $url -method $method \
-headers $headers -query $data]}]} {
return "error"
}
}
if {[string compare -nocase $method "HEAD"] == 1} {
set res [http::data $tok]
} else {
set res [http::status $tok]
}
http::cleanup $tok
return $res
}
#
# Call the /admin/ping servlet
#
method ping {} {
set myurl "$server/solr"
if {[string length $path] < 1} {
append myurl "/admin/ping"
} else {
append myurl "/$path/admin/ping"
}
set headerl ""
set res [my send_request $myurl HEAD $headerl]
return $res
}
#
# Simple Search interface
# params is a list, give this funcition name-value pair parameter
#
method search {query {offset 0} {limit 10} {params ""}} {
set myurl "$server/solr"
if {[string length $path] < 1} {
append myurl "/select"
} else {
append myurl "/$path/select"
}
lappend params q $query
lappend params wt $solr_writer
lappend params start $offset
lappend params rows $limit
set querystring [http::formatQuery {*}$params]
#
# The return data format is defined by wt, $solr_writer setting.
#
set headerl [list Content-Type "application/x-www-form-urlencoded; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $querystring]
return $res
}
#
# parameters - a list include key-value pair
#
method add {parameters {OVERWRITE true} {BOOST "1.0"} {COMMIT true}} {
# Try to build our XML document
set doc [dom createDocument add]
set root [$doc documentElement]
$root setAttribute overwrite $OVERWRITE
set docnode [$doc createElement doc]
$docnode setAttribute boost $BOOST
$root appendChild $docnode
foreach {key value} $parameters {
set node [$doc createElement field]
$node setAttribute name $key
$node appendChild [$doc createTextNode $value]
$docnode appendChild $node
}
set myaddString [$root asXML]
set myurl "$server/solr"
set params [list commit $COMMIT]
set querystring [http::formatQuery {*}$params]
if {[string length $path] < 1} {
append myurl "/update?$querystring"
} else {
append myurl "/$path/update?$querystring"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $myaddString]
return $res
}
#
# xmldata - xml data string want to add
#
method addData {xmldata {COMMIT true}} {
set myurl "$server/solr"
set params [list commit $COMMIT]
set querystring [http::formatQuery {*}$params]
if {[string length $path] < 1} {
append myurl "/update?$querystring"
} else {
append myurl "/$path/update?$querystring"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $xmldata]
return $res
}
#
# The <commit> operation writes all documents loaded since the last
# commit to one or more segment files on the disk
#
method commit {{WAITSEARCHER true} {EXPUNGEDELETES false}} {
set mycommitString "<commit waitSearcher=\"$WAITSEARCHER\" expungeDeletes=\"$EXPUNGEDELETES\"/>"
set myurl "$server/solr"
if {[string length $path] < 1} {
append myurl "/update"
} else {
append myurl "/$path/update"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $mycommitString]
return $res
}
#
# The <optimize> operation requests Solr to merge internal data structures
# in order to improve search performance.
#
method optimize {{WAITSEARCHER true} {MAXSegments 1}} {
set myoptimizeString "<optimize waitSearcher=\"$WAITSEARCHER\" maxSegments=\"$MAXSegments\"/>"
set myurl "$server/solr"
if {[string length $path] < 1} {
append myurl "/update"
} else {
append myurl "/$path/update"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $myoptimizeString]
return $res
}
#
# "Delete by ID" deletes the document with the specified ID
#
method deleteById {ID {COMMIT true}} {
set mydeleteString "<delete><id>$ID</id></delete>"
set myurl "$server/solr"
set params [list commit $COMMIT]
set querystring [http::formatQuery {*}$params]
if {[string length $path] < 1} {
append myurl "/update?$querystring"
} else {
append myurl "/$path/update?$querystring"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $mydeleteString]
return $res
}
#
# "Delete by Query" deletes all documents matching a specified query
#
method deleteByQuery {QUERY {COMMIT true}} {
set mydeleteString "<delete><query>$QUERY</query></delete>"
set myurl "$server/solr"
set params [list commit $COMMIT]
set querystring [http::formatQuery {*}$params]
if {[string length $path] < 1} {
append myurl "/update?$querystring"
} else {
append myurl "/$path/update?$querystring"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $mydeleteString]
return $res
}
#
# Uploading Data by using Apache Tika
#
method upload {fileContent {FILENAME ""} {COMMIT true} {ExtractOnly false} {params ""}} {
set myurl "$server/solr"
lappend params commit $COMMIT extractOnly $ExtractOnly
if {[string length $FILENAME] > 1} {
lappend params "resource.name" $FILENAME
}
set querystring [http::formatQuery {*}$params]
if {[string length $path] < 1} {
append myurl "/update/extract?$querystring"
} else {
append myurl "/$path/update/extract?$querystring"
}
set headerl [list Content-Type "text/xml; charset=UTF-8"]
set res [my send_request $myurl POST $headerl $fileContent]
return $res
}
}
Test code:
#!/usr/bin/tclsh
package require solr4tcl
set solrresquest [Solr_Request new "http://localhost:8983"]
$solrresquest setDocumentPath gettingstarted
# support xml, json or csv
$solrresquest setSolrWriter xml
set res [$solrresquest ping]
if {[string compare -nocase $res "ok"]!=0} {
puts "Apache Solr server returns not OK, close."
exit
}
set res [$solrresquest search "foundation"]
puts "Search result:"
puts $res
set parameters [list authors "Patrick Eagar" subject "Sports" dd "796.35" \
isdn "0002166313" yearpub "1982" publisher "Collins"]
set res [$solrresquest add $parameters true]
puts $res
set res [$solrresquest commit]
puts $res
set res [$solrresquest optimize]
puts $res
set res [$solrresquest deleteById "0002166313"]
puts $res
set res [$solrresquest deleteByQuery "publisher:Collins"]
puts $res
#set size [file size "./solr-word.pdf"]
#set fd [open "./solr-word.pdf" {RDWR BINARY}]
#fconfigure $fd -blocking 1 -encoding binary -translation binary
#set data [read $fd $size]
#close $fd
#set res [$solrresquest upload $data "solr-word.pdf"]
#puts $res
set res [$solrresquest search "pdf"]
puts "Search result:"
puts $res
Apache Solr 沒有像 Apache CouchDB 一樣,有將 REST API 做一個整理表,所以我只是對 search 的部份做一個簡單的 search method,然後確定有正確的回應回來(而不是無法連線,或者是傳回來一個網頁不存在的 404 錯誤網頁,如果有執行 Solr 的 Solr Quick Start)。
更新 2015/12/29:
加入上傳檔案和 index 處理的部份
更新 2016/01/02:
更新 method ping 的參數
2015-12-26
PostgreSQL extension: hstore
PostgreSQL: hstore
厲害的地方在於,不只可以放一個 key-value pair,而是可以在一個 column 上放一個以上的 key-value pair。
在 Windows 平台上測試最近安裝的 PostgreSQL 9.4.5 是否有支援 hstore:
得到 extension "hstore" already exists 的答案。
更新:列出目前系統上的 extension name:
厲害的地方在於,不只可以放一個 key-value pair,而是可以在一個 column 上放一個以上的 key-value pair。
在 Windows 平台上測試最近安裝的 PostgreSQL 9.4.5 是否有支援 hstore:
package require tdbc::postgres
tdbc::postgres::connection create db -user postgres -password postgres -port 5432
set statement [db prepare {
CREATE EXTENSION hstore
}]
$statement foreach row {
puts $row
}
$statement close
db close
得到 extension "hstore" already exists 的答案。
更新:列出目前系統上的 extension name:
package require tdbc::postgres
tdbc::postgres::connection create db -user postgres -password postgres -port 5432
set statement [db prepare {
select extname from pg_extension
}]
$statement foreach row {
puts $row
}
$statement close
db close
2015-12-24
SSDB 與 retcl
SSDB
retcl: Tcl client library for Redis
看完了 SSDB 寫的 features,所以我可以拿一個 Redis 的 client 來連線並且測試囉?閱讀 SSDB 的文件,SSDB 的 port 是 8888。
接下來使用 retcl 的範例進行一些測試,真的可以直接使用(除了 Publish / Subscribe and callbacks, Handling errors 我沒試,另外 retcl Commands pipelining 的範例要先 set i 0,總之要先設定 i 的值),SSDB 有些 command 回來的反應和說明不太一致(例如 info 只傳回 OK),不過大體上 SSDB 確實是 Redis API compatible,也就是如果 Redis client 寫的彈性一點,理論上就可以無痛的拿來 SSDB 這邊使用。
PS. 不要嘗試在 Windows 平台使用 SSDB,雖然在網路上可以找到 binary files,但是跟作者網站上講的一樣,不建議在 Windows 平台上使用。
Features
- An alternative to Redis, 100x Redis
- LevelDB client-server support, written in C/C++
- Redis API compatible, Redis clients are supported
- Designed to store collection data, such as list, hash, zset...
- Client API supports including C++, PHP, Python, Java, Go
- Persistent queue service
- Replication(master-slave), load balance
retcl: Tcl client library for Redis
看完了 SSDB 寫的 features,所以我可以拿一個 Redis 的 client 來連線並且測試囉?閱讀 SSDB 的文件,SSDB 的 port 是 8888。
retcl create r 127.0.0.1 8888
接下來使用 retcl 的範例進行一些測試,真的可以直接使用(除了 Publish / Subscribe and callbacks, Handling errors 我沒試,另外 retcl Commands pipelining 的範例要先 set i 0,總之要先設定 i 的值),SSDB 有些 command 回來的反應和說明不太一致(例如 info 只傳回 OK),不過大體上 SSDB 確實是 Redis API compatible,也就是如果 Redis client 寫的彈性一點,理論上就可以無痛的拿來 SSDB 這邊使用。
PS. 不要嘗試在 Windows 平台使用 SSDB,雖然在網路上可以找到 binary files,但是跟作者網站上講的一樣,不建議在 Windows 平台上使用。
couchdbtcl: rename oauth-1.0.tm
couchdbtcl
我沒注意到 tcllib 中已經有 package 名稱是 oauth,雖然我測試的時候可以正確執行,不過為了避免套件名稱衝突,所以 oauth-1.0.tm 被我改名為 myoauth-1.0.tm,提供的套件從 oauth 變成 myoauth。
我沒注意到 tcllib 中已經有 package 名稱是 oauth,雖然我測試的時候可以正確執行,不過為了避免套件名稱衝突,所以 oauth-1.0.tm 被我改名為 myoauth-1.0.tm,提供的套件從 oauth 變成 myoauth。
訂閱:
文章 (Atom)