Coral8 Stream reader in Powershell

A little something I cooked up last night

# ./Get-C8Tuple ccl://localhost:6789/Stream/Default/Proj/outStream 
param([string]$curl,[int]$maxRows=-1)

function Resolve-Url($url)
{
    $wc = new-object Net.WebClient
    $urib = [UriBuilder] $url
    $urib.Scheme = "http"
    $urib.Path= "/Manager/ResolveUri"
    $wc.UploadString($urib.uri,$url)
}

function Get-TD($url)
{
    $urib = [UriBuilder] $url
    $urib.Scheme = "http"
    $urib.Path= "/Manager"
    $wc = new-object Net.WebClient
    $wc.Headers.Add("Content-Type",'application/soap+xml; charset=utf-8; action="urn:coral8.com:SOAPAction"')
    $soapBody = "<soap:Envelope xmlns:soap='http://www.w3.org/2003/05/soap-envelope' xmlns:soapenc='http://www.w3.org/2003/05/soap-encoding' xmlns:tns='urn:coral8.com:Manager' xmlns:types='urn:coral8.com:Manager/encodedTypes' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'><soap:Body> <tns:GetTD><uri xsi:type='xsd:string'>$url</uri></tns:GetTD></soap:Body></soap:Envelope>"
    $soapResp = $wc.UploadString($urib.uri,$soapBody)
    $td = ([xml]$soapResp).Envelope.Body.GetTDResponse.Return."#text"
    ([xml]$td).TupleDescriptor.Field    
}

function ConvertFrom-C8CSV($csv,$names,$types)
{
    # TODO - support quoted csv values
    $vals = $csv.Split(",")
    $o = new-object PSObject
    
    for ($ii=0;$ii -lt $vals.Count;$ii++)
    { 
        $t = $types[$ii]
        if ($t -eq "datetime")
        {
            $v = ([datetime]"1/1/1970 GMT").AddTicks( ([long]$vals[$ii]) * 10 )
        }
        else
        {
            $v =  $vals[$ii] -as $t
        }
        $o | add-member -membertype noteproperty -name $names[$ii] -value $v
    }
   return $o
}

function ConvertFrom-C8TypeName([string] $c8Type)
{
    switch -wildcard ($c8Type)
    {
        "Integer*" { return "int" }
        "Long*" { return "long" }
        "Float*" {return "double" }
        "Bool*" { return "bool" }
        "String*" { return "string" }
        "Time*" { return "datetime" }
        "XML*" { return "xml" }
        default { throw "Type '$c8Type' not implemented" }
    }
}

write-progress "Resolve URL" "Pending"
$url = Resolve-Url $curl
$td = Get-TD $curl
$fieldNames = @("Timestamp") + ($td | % { $_.Name })
$fieldTypes = @("datetime") + ($td | % { ConvertFrom-C8TypeName $_.type })
write-progress "Resolve URL" "Done"

$urib = [UriBuilder] $url
$urib.Scheme = "http"
$req = [Net.WebRequest]::Create($urib.uri)
$req.Headers.Add('X-C8-StreamFormat', 'CSV')
$req.Headers.Add('X-C8-StreamFormatOptions', 'TitleRow=false')
$req.Method = "GET"
$resp = $req.GetResponse()
$rdr = [IO.StreamReader] $resp.GetResponseStream()
$cnt=0
while ($MaxRows -eq -1 -or $cnt -lt $MaxRows)
{
    write-progress "Reading tuples" "in progress" -currentOperation "count - $cnt"
    $csv = $rdr.ReadLine()
    ConvertFrom-C8CSV $csv $fieldNames $fieldTypes
    $cnt++
}
$resp.Close()

Code comments -

  • I couldn't find a WSDL for the manager service or a light weight .net/powershell SOAP api, so I had to resort to sending in a canned request.
  • A nice Powershell feature is how the casting operator will search the type's constructors to new up the object needed. I love it.

No Comments