2017-06-17

執行程式並且取得標準輸出的結果

set var [list ls -l]
catch {exec {*}$var} result

set lines [split $result "\n"]
foreach line $lines {
    if {[string index $line 0] == "d"} {
        puts $line
    }
}

只是用來練習的程式。使用 exec 來執行程式 (ls -l),取得結果以後再來處理。

2017-06-14

Using Nashorn from Java code (TclBlend version)

package require java

java::import javax.script.ScriptEngine
java::import javax.script.ScriptEngineManager
java::import javax.script.ScriptException

set manager [java::new ScriptEngineManager]
set nashorn [$manager getEngineByName "nashorn"]
set value [$nashorn eval "10 + 20"]
puts "Result: [$value toString]"

Nashorn 是使用 Java 寫的 JavaScript runtime,for Java 8 使用。目前支援的規範是 ECMAScript 5.1。

這裡透過 Nashorn 來執行 JavaScript code。我只是使用 TclBlend 執行 sample code 測試看看。

2017-06-13

apply

set twice {{f v} {apply $f [apply $f $v]}}
set f {{v} {return [expr $v + 5]}}

puts [apply $twice $f 10]

這只是在說明,你可以將匿名函數的內容設給一個變數,然後使用 apply 來呼叫。

2017-06-05

tclhttpd-markdown

tclhttpd-markdown


Tcllib 在 1.18 中 提供了 Markdown 套件,可以將 Markdown 格式轉換為 HTML 的工具。為了檢視這個套件目前的情況,所以作了一個簡略的 TclHttpd 支援。如果是 *.md 檔案,就使用 Tcllib Markdown 套件進行轉換,然後傳回 UTF-8 編碼的 HTML。

我想使用其它的 Markdown 轉換工具應該也是可以,只要修改轉換的部份和提供正確的 package require 就可以才對。

2017-06-04

Apache Tomcat, CGI and Tcl

最近使用 Apache Tomcat 在測試一些東西,所以同時也測試一下如何設定 CGI 以執行 Tcl CGI scrpits 的設定。

預設中 CGI 是 disable 的。在 Apache Tomcat 下使用 Tcl 來撰寫 CGI 程式,需要設定 conf/web.xml 與 conf/context.xml。 可以參考 Apache Tomcat 的文件

首先要設定 web.xml,開啟 CGIServlet 的支援,並且設定執行的程式。 如果是修改 conf/web.xml,那效果是全域性的。如果修改 WEB-INF/web.xml,就只侷限在你的 web application。
    <servlet>
        <servlet-name>cgi</servlet-name>
        <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
        <init-param>
          <param-name>cgiPathPrefix</param-name>
          <param-value>WEB-INF/cgi</param-value>
        </init-param>
        <init-param>
          <param-name>executable</param-name>
          <param-value>/usr/bin/tclsh</param-value>
        </init-param>        
        <load-on-startup>5</load-on-startup>
    </servlet>

與 URL mapping:
    <servlet-mapping>
        <servlet-name>cgi</servlet-name>
        <url-pattern>/cgi-bin/*</url-pattern>
    </servlet-mapping>

再來是 context.xml,設定 Context 的 privileged 屬性為 true(但是要注意,這樣的更改是全域設定):
<Context privileged="true">

在 webapps/ROOT/WEB-INF 目錄中建立一個新的目錄 cgi。 接下來將我們的 Tcl CGI script 放在 cgi 目錄就可以了。舉例來說,如果是 hello.tcl,網址就是:
http://localhost:8080/cgi-bin/hello.tcl

如果不要在根目錄,舉例來說,可以在 webapps 下建立一個目錄 myapp,myapp 目錄下再建立一個目錄 WEB-INF, 然後 WEB-INF 目錄下再建立目錄 cgi。

接下來將我們的 Tcl CGI script 放在 cgi 目錄,如果正確設定就可以執行。舉例來說,如果是 hello.tcl,網址就是:
http://localhost:8080/myapp/cgi-bin/hello.tcl

2017-05-19

Tcl extension and TDBC driver for CrateDB database : cratedb-tcl 0.1

Source code:
cratedb-tcl


如果需要知道 CrateDB 的一些資料:
CrateDB


因為 CrateDB REST API 支援 Parameter Substitution,所以實際上可以用來模擬 prepare/execute 的行為,這個套件為了驗證這個想法而寫的。

也就是實際上是使用 TclCurl 發出 POST request,然後取得結果。而為了模擬,所以我們將步驟分為幾個部份:
  • prepare: 取得 SQL code,只是放在某個變數中
  • param: 使用者設定參數的型別 (TYPE) 與值 (VALUE)
  • 當使用者呼叫 execute,我們將前面二者的資料結合並且設定好 Parameter Substitution 以後,發出 POST request 然後取得結果
而因為模擬了 prepare/execute,所以我們就可以使用 TDBC 中的 ::tdbc::tokenize 分析 SQL 並且進行參數代換的工作,這部份完成以後,就有一個基本可用的 TDBC driver。

但是需要注意的是因為是用模擬的,跟一般資料庫的行為還是有一些差距,當設定  PARAM 時如果沒有為某個欄位指定 TYPE/VALUE,一般會設為 NULL,雖然 TDBC 的部份我有做一些處理,但是還是沒辦法跟一般的資料庫行為完全一樣。

讓我驚嚇的部份是 CrateDB 欄位部份會自動按照變數 欄位的字母大小排序,也就是在 insert 時不指定欄位順序的話,就會出現插入資料到錯誤的欄位。我反覆測試的時候發現的,目前不知道是 CrateDB 的設計還是 bug。

TclCurl DELETE request (using -customrequest)

package require TclCurl

proc httpBlobDelete {url} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -customrequest DELETE
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 204} {
        return -code ok
    } elseif {$responsecode == 404} {
        return -code error "Not Found"
    } else {
            return -code error "ERROR"
    }
}

用來測試 CrateDB REST API 中 BLOB delete 的程式。

如果 TclCurl 要指定 DELETE request,使用 -customrequest 來指定。因為 CrateDB 會回傳 status code 來表示檔案已成功刪除 (204),或者是沒有這個檔案 (404),所以取得 responsecode 以後判斷。大致上是這樣。


更新:
CrateDB 加入 BLOB 資料使用 PUT,下面是測試的程式:
package require TclCurl

proc httpBlobPut {url data} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -customrequest PUT -postfields $data
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 201} {
        return -code ok
    } elseif {$responsecode == 409} {
        return -code error "Conflict"
    } else {
            return -code error "ERROR"
    }
}


使用 GET 讀取內容:
proc httpBlobGet {url} {
    set curlHandle [curl::init]
    $curlHandle configure -url $url -bodyvar html
    catch { $curlHandle perform } curlErrorNumber
    if { $curlErrorNumber != 0 } {
        return -code error [curl::easystrerror $curlErrorNumber]
    }
    
    set responsecode [$curlHandle getinfo responsecode]
    $curlHandle cleanup
    
    if {$responsecode == 200} {
        return -code ok $html
    } elseif {$responsecode == 404} {
        return -code error "Not Found"
    } else {
            return -code error "ERROR"
    }
}

2017-05-16

tclmonetdb v0.9.6

Homepage


tclmonetdb

About


MonetDB is an open source column-oriented database management system developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands.

MonetDB excessively uses main memory for processing, but does not require that all data fit in the available physical memory. To handle a dataset that exceeds the available physical memory, MonetDB does not (only) rely on the available swap space, but (also) uses memory-mapped files to exploit disk storage beyond the swap space as virtual memory.

tclmonetdb is a Tcl extension by using MAPI library to connect MonetDB.

一些說明

  1. Add more string to monetdbSuffixes

非常小的更新,不過可以改進我自己的使用情況。

在最近我試著自己建立 MoneDB 的 openSUSE RPM(這樣可以簡化我在安裝上的步驟),觀察 RPM spec 與使用 rpm -qpl 列出檔案,MoneDB 是這樣分類的:
MonetDB-client-11.25.21 -
/usr/bin/mclient
/usr/bin/msqldump
/usr/lib64/libmapi.so.8
/usr/lib64/libmapi.so.8.0.1
/usr/share/licenses/MonetDB-client
/usr/share/licenses/MonetDB-client/COPYING
/usr/share/man/man1/mclient.1.gz
/usr/share/man/man1/msqldump.1.gz

MonetDB-client-devel-11.25.21 -
/usr/include/monetdb
/usr/include/monetdb/mapi.h
/usr/lib64/libmapi.so
/usr/lib64/pkgconfig/monetdb-mapi.pc

所以如果我只想要安裝 MonetDB-client-11.25.21,我就需要更新 monetdbSuffixes,讓 tclmonetdb 會去找 libmapi.so.8 並且載入。所以決定做一個小更新來因應這件事。

2017-05-15

tclmonetdb v0.9.5

Homepage


tclmonetdb

About


MonetDB is an open source column-oriented database management system developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands.

MonetDB excessively uses main memory for processing, but does not require that all data fit in the available physical memory. To handle a dataset that exceeds the available physical memory, MonetDB does not (only) rely on the available swap space, but (also) uses memory-mapped files to exploit disk storage beyond the swap space as virtual memory.

tclmonetdb is a Tcl extension by using MAPI library to connect MonetDB.

一些說明

  1. Add monet_version method

增加 monet_version 取得 MonetDB 目前的版本。使用的方式為查詢 sys.environment 的方式,取得目前 monet_version 的值。這個方式有個缺點,就是需要有存取的權限,如果權限不足,就會回傳空白的結果。

2017-05-14

info library

info library

info library returns the name of the library directory in which standard Tcl scripts are stored.

我忘記我有沒有記錄過這件事,就是 openSUSE 和 Ubuntu 如果你使用 info library 取得資訊,openSUSE (64 位元) 是在 /usr/lib64/tcl/tcl8.6,但是 Debian/Ubuntu 使用不同的方式來組織 32/64 位元目錄,所以會拿到不同的資訊。

如果是純粹 Tcl 所撰寫的套件,openSUSE 也有可能會放在 /usr/share/tcl 這個目錄下面。