sexta-feira, 13 de julho de 2012

Garantindo a confiabilidade de arquivos do Siebel

A algum tempo atrás eu criei uma apresentação para uma equipe técnica sobre como garantir a confiabilidade de arquivos relacionados ao Siebel e que eram disponibilizados para cópia para terceiros.

A apresentação foi feita considerando o cenário da empresa, mas eu fiz algumas adaptações e disponibilizei-a no Dropbox para download.

Boa leitura!


quarta-feira, 27 de junho de 2012

Fazendo as pazes com o proxy chato da Microsoft

Boa parte dos aplicativos hoje em dia possuem suporte a conexão à Internet, seja para verificar atualizações, permitir o download de novas funcionalidades ou simplesmente porque eles dependem de acesso à Internet para funcionarem direito.

Para quem trabalha dentro de uma rede Microsoft, a vida pode ser mais difícil com isso: o que fazer quando você se depara com um servidor proxy da Microsoft que possui autenticação via Active Directory?  Não são muitos os aplicativos que suportam este tipo de autenticação e nestes casos você fica ver navios se o acesso a Internet depende exclusivamente do proxy.

Eu já havia tentando no passado algumas soluções mas todas elas eram insatisfatórias, seja porque não funcionavam mesmo ou porque eram complicadas demais.

A alguns meses atrás eu conheci o programa de código aberto CNTLM que resolveu todos estes meus problemas de forma muito elegante.

O CNTLM é um proxy escrito em C que se encarrega das seguintes funções:
  1. Fazer a autenticação no Active Directory com seu login para todas as suas aplicações que o utilizarem para acessar à internet;
  2. Realizar a comunicação com os proxies internos da rede Microsoft para obter dados via HTTP/HTTPS.
Para fazer isto, basta realizar o download do aplicativo em http://sourceforge.net/projects/cntlm/files/cntlm/e instalar no seu computador. Repare que o CNTLM está disponível para os sistemas operacionais Windows e Linux (sendo que para este existem pacotes RPM e DEB). Eu vou utilizar a versão disponível para Windows para demonstrar o aplicativo, instalando o mesmo em um Windows XP.

Depois de instalar o aplicativo é necessário configurá-lo. Um dos passos é gerar um hash com seu login e senha para armazenar isto no arquivo de configuração. Isto é muito mais seguro do que você guardar a senha descriptografada.

Em um prompt do cmd.exe, digite:

C:\Program Files\Cntlm>cntlm.exe -H -u alceu-d foobar
cygwin warning:
  MS-DOS style path detected: C:\Program Files\Cntlm\cntlm.ini
  Preferred POSIX equivalent is: /Cntlm/cntlm.ini
  CYGWIN environment variable option "nodosfilewarning" turns off this warning.
  Consult the user's guide for more details about POSIX paths:
    http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Password:
PassLM          BDD3947C2A2F7A7FCDEB7B279523CCD5
PassNT          4957D58E48C9BEDF850B8FA8CEDFFED6
PassNTLMv2      FC8E3B7326F4FD313FA6D1A5E550614F    # Only for user 'alceu', domain 'foobar'

São três os hashes gerados, mas o mais recomendável é utilizar o PassNTLMv2 por ter criptografia mais forte. Pode ser que seu proxy não aceite este método, então você deverá tentar os outros.

Apenas copie a linha toda para seu arquivo de configuração (cntlm.ini) conforme é mostrado abaixo:

# NOTE: Use plaintext password only at your own risk
# Use hashes instead. You can use a "cntlm -M" and "cntlm -H"
# command sequence to get the right config for your environment.
# See cntlm man page
# Example secure config shown below.
# PassLM          1AD35398BE6565DDB5C4EF70C0593492
# PassNT          77B9081511704EE852F94227CF48A793
### Only for user 'testuser', domain 'corp-uk'
# PassNTLMv2      D5826E9C665C37C80B53397D5C07BBCB
#PassLM          D3D468DBC2224BD737E9981628C73A26
#PassNT          9C9672B7DAB8012768F515C2DCE69C2E
PassNTLMv2      FC8E3B7326F4FD313FA6D1A5E550614F    # Only for user 'alceu', domain 'foobar'

Após isso, configure os proxies da rede que o CNTLM deverá utilizar para comunicação com a Internet.

# List of parent proxies to use. More proxies can be defined
# one per line in format <proxy_ip>:<proxy_port>
#
#Proxy        10.0.0.41:8080
Proxy        proxy1.foobar.com:80
Proxy        proxy2.foobar.com:80

Você pode optar por excluir endereços e nomes de máquinas que não deseja que utilizar o proxy para acessar:

# List addresses you do not want to pass to parent proxies
# * and ? wildcards can be used
#
#NoProxy        localhost, 127.0.0.*, 10.*, 192.168.*
NoProxy        localhost, 127.0.0.*

Defina também a porta que o CNTLM deverá utilizar para escutar. Eu utilize a porta abaixo para evitar conflitos mas você pode utilizar a porta que achar melhor:

# Specify the port cntlm will listen on
# You can bind cntlm to specific interface by specifying
# the appropriate IP address also in format <local_ip>:<local_port>
# Cntlm listens on 127.0.0.1:3128 by default
#
Listen        60000

Se você quiser usar uma máquina virtual na sua máquina, essa opção abaixo será necessária mas não se esqueça também de limitar por IP quem poderá acessar o seu proxy por questões de segurança.

# Enable to allow access from other computers
#
Gateway    yes

# Useful in Gateway mode to allow/restrict certain IPs
# Specifiy individual IPs or subnets one rule per line.
#
#Allow        127.0.0.1
#Deny        0/0
#Allow        172.19.0.95

Por último, e não menos importante, especifique qual cabeçalho HTTP User-Agent o CNTLM deverá usar. Se o administrador da rede for especialmente paranóico, você poderá evitar questionamentos ocultando seus clientes web "não oficiais" da forma mostrada abaixo:

# Headers which should be replaced if present in the request
#
Header        User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)

Por último, será necessário configurar seus programas para que utilizem o CNTLM. Eu, por exemplo, faço uso extensivo do programa ppm do ActivePerl para instalar módulos na máquina. A maneira de fazer o ppm utilizar o CNTLM é configurar uma variável de ambiente chamada HTTP_PROXY tendo como valor o endereço do CNTLM e a porta aonde ele escuta as requisições. A figura abaixo ilustra a configuração disto no Windows.


Utilizando uma máquina virtual do CentOS no Windows com VMware eu também pude utilizar o yum para instalar novos pacotes RPM de maneira similar exportando a variável de ambiente HTTP_PROXY com o endereço IP da máquina hospedeira. É possível também usar o yum.conf para isto (veja mais em http://www.centos.org/docs/5/html/yum/sn-yum-proxy-server.html).

O CNTLM é instalado no Windows como um serviço, então você poderá pará-lo, iniciá-lo ou reiniciá-lo a qualquer momento da mesma forma como faria com qualquer serviço no Windows.

Também é possível iniciar o CNTLM para realizar debugging das conexões. Para isto, basta executar no prompt o seguinte comando:

cntlm -f -s -v

Com as opções de linha de comando mostradas acima, o CNTLM irá realizar a serialização das requisições (para não fazê-las em paralelo), rodando o aplicativo em modo foreground e imprimindo mensagens detalhadas sobre as requisições e respostas obtidas.

O CNTLM ainda possui mais recursos e eles estão todos bem documentados. Consulte a documentação para mais detalhes do que o aplicativo pode fazer.

Assim, com alguns minutos de trabalho você consegue utilizar seus programas que precisam de algum tipo de acesso à Internet sem muito esforço e respeitando as regras de acesso na rede Microsoft que você utiliza!

domingo, 10 de junho de 2012

Melhorando o desempenho da base local do Siebel

Então está lá você, trabalhando com sua base local do Siebel do Tools e assim que começa a compilar um SRF logo fica pensando em algo melhor para fazer do que escutar o disco rígido trabalhando como uma pipoqueira enquanto a compilação não acaba...

A base local do Siebel é um DBF do Anywhere, um banco de dados móvel da Sybase. Consiste de um único arquivo salvo no diretório de instalação das ferramentas do Siebel.

Conforme linhas são inseridas, removidas ou atualizadas no banco, a tendência é ter fragmentação no arquivo, e depois de algum tempo isso pode começar a se tornar um inconveniente pois quanto mais fragmentada a base pior o desempenho para leitura e escrita na mesma. Levando em consideração que uma base local pode facilmente passar os 700Mb recomendados pela Oracle para tamanho máximo, não é difícil ter sua base local fragmentada.

A fragmentação do disco é bem conhecida em sistemas operacionais da Microsoft (que já dispõe de ferramentas de longa data para resolver este problema) mas e quando a fragmentação está apenas em um arquivo?

O programa Contig, desenvolvido pelos criadores do antigo website Sysinternals, foi criado justamente para resolver este tipo de problema: utilizando as mesmas APIs padrão de desfragmentação de arquivos do Windows, esse programinha consegue colocar todos os setores de alocação de um arquivo em sequência, o que é especialmente útil no caso da base local do Siebel. Veja um exemplo de desfragmentação abaixo:


Eu adoraria ter um benchmark para desmonstrar qual a diferença de trabalhar em uma base local fragmentada ou não, mas não tive tempo hábil de conduzir um teste desses. A realidade é que se a base local estiver realmente fragmentada, você irá sentir a diferença quando tentar repetir uma operação depois da desfragmentação.

Claro, esse truque só irá funcionar se a partição aonde a base local reside está desfragmentada: se não houver espaço contínuo também para alocar o arquivo, o Contig de nada ajudará.

Pensando nisso, é útil criar uma partição separada no disco, exclusivamente para uso da base local. Com discos rígidos a preços bastante convidativos, separar um 1Gb para uma base local deve ser suficiente para a maioria dos casos. Como a partição terá somente um arquivo, a fragmentação ali será bem menor.

Discos mais rápidos obviamente irão ajudar: se você puder dispor de um disco SSD, melhor ainda.

Algum tempo atrás eu tentei encontrar uma solução para utilização de ramdisk, mas além do risco com relação à perda de dados, não encontrei nenhuma ferramenta gratuita para Windows que conseguisse criar um ramdisk de tamanho razoável para armazenar a base local.

E, se tiver você estiver com disposição, ainda de quebra a Sybase tem um white paper em http://www.sybase.com/detail?id=1023801 com mais informações sobre como melhorar o desempenho do banco de dados Anywhere, mas eu mesmo não testei as ferramentas considerando que o que é disponibilizado junto com os instaladores do Siebel é o absolutamente mínimo para trabalhar. Especialmente falando na dica 10 ("Tip 10: Ready, steady, rebuild"), na falta da ferramenta citada sempre é possível fazer um novo database extract e obter uma base local novinha.

terça-feira, 5 de junho de 2012

Clusters de imagem única no Linux

Já ouviu falar em clusters de imagem única? Não?

Bem, em 2011 eu entreguei meu trabalho de conclusão de curso (TCC) da pós-graduação na FIAP (em Sistemas Corporativos de Alto Desempenho). Me pareceu que o tema era bastante aderente ao currículo do curso... e foi mesmo!

A ideia original partiu do livro "Computação em Cluster" (do Carlos Pitanga) que apresentava o projeto openMosix como um cluster de imagem única para Linux, que juntamente com o Bewoulf, oferecia um suporte robusto para aplicações distribuídas que funcionassem à partir de criação de processos filhos para paralelizar o processamento de uma tarefa qualquer.

Bem, o fato de que o projeto do openMosix foi descontinuado em 2008 (por motivos bastante obscuros por sinal) dificultou um "pouco" o processo, já que meu TCC incluía testes práticos além da referência bibliográfica.

O resultado final pode ser visto no PDF que disponibilizei em http://db.tt/iWxgKThV.

Obviamente os projetos analisados já devem ter evoluído alguma coisa desde a data de publicação do TCC, mas com certeza a dissertação ainda serve como introdução ao assunto, além de ser possível acompanhar alguma escovação de bits com Linux e Perl.

Adoraria receber críticas (construtivas!) sobre o TCC, então fique à vontade para usar o espaço para comentários no final da postagem.

domingo, 29 de abril de 2012

Desfragmentando automaticamente o HD de um servidor Siebel

Bem, se você chegou até aqui é porque passou do título do artigo e não pensou "caramba, eu gerencio um servidor Siebel em um sistema operacional com sistema de arquivos decente, eu não preciso saber disto".

Ainda por aqui? Bem, então é porque provavelmente tem um servidor Siebel instalado em alguma versão do Microsoft Windows Server e com unidades de disco em estado deprimente de fragmentação porque ninguém se lembra de fazer isto, principalmente se o servidor em questão é utilizado para desenvolvimento ou QA.

Já faz algum tempo que eu resolvi (meio que por falta de opção, para dizer a verdade) fazer automações com Windows Powershell e descobri como automatizar a desfragmentação de um servidor Siebel sem nenhuma intervenção manual.

Para fazer isto, eu usei o programa defrag.exe que está disponível por padrão na instalação do Windows e algum código em Powershell 2 para parar os serviços do Siebel e reiniciá-los quando defrag.exe acabar seu trabalho. De quebra, o script ainda gera um arquivo de registro rudimentar para revisão.

Segue o código abaixo para fazer isto:

set-strictmode -version 2.0

# a ordem aqui é importante: parar o IIS, parar o serviço do servidor Siebel e
# parar o serviço do SiebelG Gateway
$services = @('W3SVC','siebsrvr_SIEBEL_foobar','gtwyns')
$timeToWait = 180
$now = get-date
$logFile = 'results-' + $now.Day.ToString() + $now.Month.ToString() + $now.Year.ToString() + '.txt'

'[' + $now.ToString() + '] Starting management of disks' | Out-File $logFile

try {

    foreach ($serviceName in $services) {

        "Stopping $serviceName service" | Out-File -Append $logFile
       
        $service = Stop-Service $serviceName -PassThru -Force
       
        if ( $service -ne $null ) {
           
            if ( $service.Status -ne 'Stopped' ) {
           
                throw "Could not stop $serviceName. Aborting..."
           
            } else {
           
                "$serviceName was stopped successfully" | Out-File -Append $logFile
           
            }
           
        }
       
    }
   
    "Defragmenting drives" | Out-File -Append $logFile
    "Defragmenting drive C:" | Out-File -Append $logFile
    defrag c: -v 2>&1 | Out-File -Append $logFile
    "Defragmenting drive D:" | Out-File -Append $logFile
    defrag d: -v 2>&1 | Out-File -Append $logFile
   
    [array]::Reverse($services)
   
    foreach ($serviceName in $services) {

        "Starting $serviceName service" | Out-File -Append $logFile
       
        $service = Start-Service $serviceName -PassThru
       
        if ( $service -ne $null ) {
       
            if ( $service.Status -ne 'Running' ) {
           
                throw "Could not start $serviceName. Aborting..."
           
            } else {
           
                "$serviceName was started successfully" | Out-File -Append $logFile
           
            }
       
        }
       
        "Waiting $timeToWait seconds to give time to the process start correctly" | Out-File -Append $logFile
       
        Start-Sleep -Seconds $timeToWait
       
    }   
   
} catch {

    $error[0].exception | Out-File -Append $logFile


} finally {


}

Partes interessantes para comentar do código:
  • Procure o nome dos serviços em Computer Management, Services and Application, Services (pelo menos este é um dos caminhos no Windows Server 2003, pode variar em outras versões).
  • Depois que os serviços são parados, o array é invertido para que os serviços sejam iniciados novamente na ordem correta.
  • Repare que as mensagens de saída padrão e erro padrão do defrag.exe são redirecionadas para o arquivo de log com um "2>&1" (ideia vergonhosamente copiada do que existe na maioria dos shell scritps de sistemas UNIX-like). Existem formas mais elegantes (e trabalhosas) para fazer isto com as classes System.Diagnostics.ProcessStartInfo e System.Diagnostics.Process, mas você vai ter que aprender um pouco de .Net para usá-las.
  • No caso, o script realiza a desfragmentação nas unidades C:\ e D:\ do servidor, talvez você tenha uma combinação diferente.
  • O script espera um tempinho para dar tempo dos serviços serem iniciados corretamente. O tempo necessário para isto pode variar bastante.
  • Não é que eu esqueci de colocar algo interessante dentro do block finally, eu simplesmente não achei nada interessante para fazer ali.
Depois disso, é só agendar a tarefa para executar em algum horário interessante e partir para o abraço.


Se você gosta de emoções fortes, pode até fazer isto em ambiente de produção, mas eu não faria isto se fosse você: esse tipo de coisa tem que ser bem programada e acompanhada de perto.

Este script Powershell, assim como outros, é parte do projeto de código aberto Siebel GNU Tools. O website do projeto está localizado em https://code.google.com/p/siebel-gnu-tools/.

terça-feira, 17 de abril de 2012

Com que livro eu vou?

Pode parecer piada, mas conheço muitos profissionais de informática que não leem livros da área. Já escutei até um "ler esses livros é coisa de nerd". Ahn?!?

Dizer isso não tem muito sentido, exceto talvez para aqueles que tem recursos financeiros suficientes para pagar (com frequência) um treinamento com instrutor ou psicografar o conhecimento de profissionais já desencarnados...

Eu considero que ler material técnico é uma das melhores formas de se manter atualizado ou aprender coisas novas. Com computadores pessoais (tendo capacidade de processamento considerável) e banda larga com custos acessíveis, estudar em casa através de um livro é uma boa alternativa para muitos campos da informática. O mesmo se aplica a revistas periódicas da área.

Outro argumento que escuto bastante é "tem na internet". É, realmente tem. O problema é que escrever material técnico de qualidade dá trabalho e a diferença em ler algo de qualidade boa ou ruim é que o primeiro te faz ganhar tempo ao evitar que você fique batendo cabeça por falta de informações e/ou informações incorretas.

Talvez seja por isso que o mercado editorial para a área não seja tão bom quanto poderia ser. Geralmente ficamos com as opções de ler material traduzido (e só por ser traduzido, em geral, já está desatualizado) ou livros mal editados ou com conteúdo técnico exclusivamente introdutório.

Não estou dizendo com isso que não temos obras boas: as editoras Brasport e Novatec tem feito um bom trabalho com material 100% brasileiro. E eu considero os trabalhos da editora Bookman realmente fantásticos, tanto na tradução quanto editoração e acabamento.

Mas como saber qual livro comprar? Opções existem aos montes.

Ao contrário de websites como a Amazon que possuem resenhas e notas de livros consistentes (você não vê somente elogios e as resenhas não "caducam" com o tempo) eu não tenho visto nada parecido no Brasil. Eu mesmo já publiquei resenhas em websites famosos de compras e a resenha nunca apareceu ou depois de algum tempo tomou um "chá de sumiço".

Há algum tempo atrás me apresentaram o website Skoob, que nada mais é que uma rede social exclusiva para livros. Ali é possível, ao menos, obter a nota dada por leitores de diversos livros da área de informática, isso quando não for possível ler uma resenha ou outra por aí (algo que espero que mude com o amadurecimento da rede).

Eu mesmo já arrisquei algumas resenhas por lá. Você pode vê-las em http://www.skoob.com.br/estante/resenhas/310422.

Estou com os dedos cruzados esperando que a rede no Skoob amadureça cada vez mais, afinal é uma forma independente de darmos um "empurrãozinho" no mercado editoral brasileiro para termos obras melhores e mais completas!

sábado, 31 de março de 2012

Trabalhando com arquivos no eScript

O Siebel possui sua própria linguagem script para programação: o eScript.
De acordo com as boas práticas só se programa em eScript quando não existem outras opções para aplicar a lógica de negócios no sistema (por conta de facilidade de realizar atualizações de versão no Siebel). Isso inclui, não raramente, a necessidade de ler ou escrever arquivos no sistema de arquivos aonde o servidor Siebel está instalado (ou no sistema de arquivos do Siebel Client, mas não vou falar de Browser Scripting neste artigo).
Para manipulação de arquivos o eScript oferece a biblioteca Clib: esta biblioteca oferece funções muito parecidas com aquelas existentes na linguagem ANSI C. Não vou repetir aqui o que já se encontra documentado no respectivo Siebel Bookshelf (Siebel eScript Language Reference) mas sim citar alguns macetes aprendidos depois de quebrando a cabeça por aí.

Teste o diretório antes de usá-lo


Antes de usar um diretório é sempre uma boa idéia verificar se o script tem acesso a ele (principalmente se a versão do Siebel que você está trabalhando não tem a função Clib.strerror trabalhando corretamente). Uma forma simples de testar isto é utilizar as funções Clib.chdir e Clib.getcwd em combinação, como mostrado na função testDir definida abaixo:

function testDir(dir)
{
    try
    {
        //tests if the directory is valid
        var previousDir = Clib.getcwd();
        var testResult = -1;
       
        testResult = Clib.chdir( dir );
       
        if ( testResult == -1 )
        {
            TheApplication().RaiseErrorText('The directory ' + dir + ' does not exists or cannot be accessed.');
        }
    }
    catch(e)
    {
        TheApplication().RaiseErrorText('Error in function testDir: ' + e.toString());
    }
}


Isso vai ajudar você a identificar erros de permissão (ou não existência) do diretório antes de tentar usá-lo.

Teste se o arquivo foi aberto

Parece besteira, mas às vezes acho alguns programas por aí que simplesmente não fazem um teste depois que abrem um arquivo com Clib.fopen. É muito simples fazer isto, como mostrado abaixo:

    fp = Clib.fopen(myFile,"au");

    if ( fp == null )
    {
        TheApplication().RaiseErrorText('An error ocurrered when trying to open ' + myFile);
    }


Com três linhas de código você evitará ter que fazer debugging por conta de erro nas permissões no sistema de arquivo, por exemplo. Por que isso? Porque esses erros não são considerados falhas graves: a Clib irá falhar silenciosamente...
A propósito, as funções Clib.fputs e Clib.fclose seguem o mesmo raciocínio, retornando null no caso de terem problemas. Se você estiver se sentido particularmente paranoico também pode incluir os mesmos tipos de testes.

Favoreça o uso do buffer

As funções de leitura e escrita da Clib utilizam buffer por padrão: isso quer dizer que elas guardam em memória os dados antes de realizar uma operação de E/S. Isso favorece o desempenho do seu programa porque operações de E/S em disco são mais lentas do que em memória (não estou nem considerando o cache do disco). Se você fizer isto dentro do mesmo escopo:

    fp = Clib.fopen(myFile,"au");

    if ( fp == null )
    {
        TheApplication().RaiseErrorText('An error ocurrered when trying to open ' + myFile);
    }
   
    Clib.fputs(myData,fp);
    Clib.fclose(fp);


você simplesmente desperdiça o buffer. Uma vez argumentaram comigo que utilizar Clib para mensagens de registro era reinventar a roda já que para este fim existe a função TheApplication().Trace. O problema desta função é que você não tem controle sobre o buffer: ela escreve imediatamente isto no disco, ou seja, abre o arquivo, escreve e imediatamente fecha o arquivo depois.
Já a Clib permite que você tenha controle sobre como o buffer se comporta e se você estiver escrevendo grandes quantidades de dados o buffer poderá te ajudar.
Para isto, basta criar uma variável (global, se você for usá-la durante o Business Service todo) e abrir o arquivo apenas uma vez com Clib.fopen. Após isto, basta seguir utilizando Clib.fputs e seus primos.
Como garantir então que o arquivo será fechado? Isso é particularmente um problema se o servidor Siebel está utilizando um sistema de arquivos com locking mandatório como o NTFS: seu arquivo ficará "preso" até que o processo que o executou explicitamente feche ele ou deixe de existir.
Para evitar este tipo de problema basta usar o bloco finally para fechar o arquivo.

# na área de declarations
    var fp;
   
function foobar {

    try {

    fp = Clib.fopen(myFile,"au");

    if ( fp == null )
    {
        TheApplication().RaiseErrorText('An error ocurrered when trying to open ' + myFile);
    }
   
    Clib.fputs(myData,fp);
   
    } catch(e) {
   
        //do something
   
    } finally {
   
        Clib.fclose(fp);
   
    }
   
}


Com isto, a menos que o processo que está executando o Business Service seja encerrado (e o locking arquivo liberado no processo) garantidamente o arquivo será fechado e quaisquer dados que ainda não tenha sido escritos o serão antes do arquivo ser fechado. Com isto você tem maiores garantidas de que os dados não foram perdidos (não totalmente pelo menos) e o locking do arquivo seja removido pelo sistema de arquivos.
Precisa que os dados sejam escritos (por maior garantia de não perder os dados) no arquivo a cada Clib.fputs? Use a Clib.fflush para este fim, sem fechar o arquivo.

Copiando arquivos

O artigo "How Can You Copy Files from One Location to Another Using Siebel Scripting?" (ID 477948.1) disponível na página de suporte da Oracle ensina algumas alternativas de como resolver isto já que a Clib, por algum motivo que eu não entendo muito bem, não tem funções específicas para esta funcionalidade tão comum.
Das alternativas que ele ensina, a melhor mesmo é utilizar Clib.rename: se você já usou alguma vez o prompt de algum SO UNIX ele se parece muito com o comando mv.
As outras alternativas (Clib.system e SElib) são "custosas" demais para fazer isto e mais complicadas de utilizar. Se for necessário copiar muitos arquivos, talvez seja interessante então criar um programa pequeno em outra linguagem de programação e então executá-lo com Clib.system, assim você executa este programa uma única vez e ele faz todo o trabalho de uma vez.

Listando arquivos em um diretório

Essa dica só é válida para instalações do Siebel em SO's da Microsoft (Windows).
O suporte da Oracle tem artigos ensinando a usar SElib e a DLL kernel32.dll para conseguir procurar por padrões de arquivos em algum diretório qualquer. Pena que o artigo só ajuda até certo ponto: já vi código por aí chamando a função FindFirstFileA do kernel32.dll recursivamente quando a função FindNextFileA está lá disponível justamente para resolver estas questões. É um processo doloroso ler a documentação (principalmente porque ela é para programadores C++, o que não é o meu caso) mas ela esta lá (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364418%28v=vs.85%29.aspx) justamente para evitar este tipo de bobagem.
Outro problema é lidar com caracteres nulos: um tamanho pré-definido de memória é alocada para guardar o nome do arquivo que for encontrado: na falta de algo melhor, as funções FindFirstFileA e FindNextFileA vão preencher o que restar do tamanho alocado com caracteres nulos caso o nome do arquivo seja menor. Parece normal se você estiver programando em C ou C++, mas tente concatenar strings (ou qualquer outra coisa, como usar split) com eScript e com o resultado devolvido e você verá que as coisas não vão funcionar como esperado.
A função abaixo é uma solução possível para resolver este tipo de problema: ela irá procurar o primeiro caracter nulo na string e retornar o número de caracteres "imprimíveis" lidos até então.

function removeNul(string)
{
    try
    {
        var iEndPos = string.length;
        var lastPrintChar = 0;

        for (var i = 0; i < iEndPos; i++) {
 
            //if char is printable, go to next until test fails
            if ( Clib.isprint( string.charAt(i) ) )
            {
           
                lastPrintChar++;
           
            }
            else {
           
                break;
           
            }
       
        }
       
        return string.substring(0, lastPrintChar);
   
    }
    catch(e) {
   
        logMessage('An error ocurred with removeNul function: ' + e.errText);
   
    }

}


Abaixo eu coloquei um exemplo completo de listagem de arquivos considerando estas questões que comentei, só para ilustrar os conceitos. Repare que os resultados encontrados são guardados em um array para que o garbage collector do eScript tenha oportunidade de se livrar logo da memória alocada para os objetos e kernel32.dll.

    try {

        var blob = new blobDescriptor();
        var fileData;
        var hFind;
       
        blob.dwFileAttributes = SWORD32;
        blob.ftCreationTime = SWORD32;
        blob.ftCreationTime_ = SWORD32;
        blob.ftLastAccessTime = SWORD32;
        blob.ftLastAccessTime_ = SWORD32;
        blob.ftLastWriteTime = SWORD32;
        blob.ftLastWriteTime_ = SWORD32;
        blob.nFileSizeHigh = SWORD32;
        blob.nFileSizeLow = SWORD32;
        blob.dwReserved0 = SWORD32;
        blob.dwReserved1 = SWORD32;
        blob.cFileName = 1000000;
        blob.cAlternateFileName = 1000000;
       
        var nextIndex = filesToProcess.length;
       
        // brand new start of filesToProcess
        if (typeof nextIndex == 'undefined') {
       
            nextIndex = 0;
            filesToProcess[0] = '';
       
        }
       
        hFind = SElib.dynamicLink("Kernel32.DLL", "FindFirstFileA", STDCALL, filenameToMatch, blob, fileData);

        //foi encontrado um arquivo de acordo com o padrão informado
        if (hFind != -1) {

            filesToProcess[nextIndex] = removeNul(fileData.cFileName.toString());

            while (SElib.dynamicLink("Kernel32.DLL", "FindNextFileA", STDCALL, hFind, blob, fileData) != 0)
            {
           
             nextIndex++;
            
             filesToProcess[nextIndex] = removeNul(fileData.cFileName.toString());            
           
            }
               
            return true;
        }
    }
    catch(e) {
   
        throw(e);
       
    }
    finally {
   
        nextIndex = null;
        fileData = null;
   
    }
}


Leia e escreva em Unicode

Um dos modos disponíveis para a função Clib.fopen é de leitura e escrita em Unicode através da letra "u" especificada na chamada da Clib.fopen.
Trabalhar neste modo é a melhor garantia que você pode ter de conseguir exportar ou importar dados de forma portável entre sistemas, principalmente se o banco de dados do Siebel estiver codificado em Unicode (o que, atualmente, é bem possível). Trabalhar com Unicode vai evitar dores de cabeça futuras com acentos e outras mazelas associadas com diferentes codificações de caracteres.

quinta-feira, 1 de março de 2012

Mais alguns truques com o srvrmgr

A um tempo atrás eu havia postado um artigo (Fazendo melhor uso do srvrmgr.exe) sobre o srvrmgr mas faltou falar sobre a manipulação de saída de dados, incluindo um truquezinho sujo que não está documentado. Vamos a eles.

Manipulando a saída dos comandos

É possível alterar a forma como o srvrmgr irá exibir a saída dos programas. Por exemplo, a saída padrão do comando list comp é está aqui:

srvrmgr> list comp

SV_NAME     CC_ALIAS                       CC_NAME                                   CT_ALIAS  CG_ALIAS      CC_RUNMODE   CP_DISP_RUN_STATE  CP_NUM_RUN_  CP_MAX_TASK  CP_ACTV_MTS  CP_MAX_MTS_  CP_START
_TIME        CP_END_TIME  CP_STATUS  CC_INCARN_NO  CC_DESC_TEXT
----------  -----------------------------  ----------------------------------------  --------  ------------  -----------  -----------------  -----------  -----------  -----------  -----------  --------
-----------  -----------  ---------  ------------  ------------
siebsrvdev  BusIntBatchMgr                 Business Integration Batch Manager                  EAI           Batch        Online             0            20           1            1            2012-03-
01 14:59:11
siebsrvdev  BusIntMgr                      Business Integration Manager                        EAI           Batch        Online             0            20           1            1            2012-03-
01 14:59:11
siebsrvdev  ClientAdmin                    Client Administration                               System        Background   Online             0            1                                      2012-03-
01 14:59:11
siebsrvdev  CommConfigMgr                  Communications Configuration Manager                CommMgmt      Batch        Online             0            20           1            1            2012-03-

A saída está truncada, mas isto foi proposital: é exatamente desta forma que os dados foram exibidos no meu terminal. Se você usa isto com frequência provavelmente fica meio aborrecido com o resultado não muito agradável de ler.

Isso pode ser alterado pelo comando configure list. Vamos a ajuda online dele:

srvrmgr> help configure list
  configure list <ValidListCmd> 
       [show <column_name> [ AS <column_header>]]
       [, <column_name>    [ AS <column_header>]] ....

O comando faz exatamente isto: configura um dos subcomandos disponível para o comando list. Ele permitirá que você configure, por exemplo, quais as colunas você quer que sejam exibidas. Vamos ver como está a configuração atual para o list comp:

srvrmgr> configure list comp
    SV_NAME (31):  Server name
    CC_ALIAS (31):  Component alias
    CC_NAME (76):  Component name
    CT_ALIAS (31):  Component type alias
    CG_ALIAS (31):  Component GRoup Alias
    CC_RUNMODE (31):  Component run mode (enum)
    CP_DISP_RUN_STATE (61):  Component display run state
    CP_NUM_RUN_TASKS (11):  Current number of running tasks
    CP_MAX_TASKS (11):  Maximum tasks configured
    CP_ACTV_MTS_PROCS (11):  Active MTS control processes
    CP_MAX_MTS_PROCS (11):  Maximum MTS control processes
    CP_START_TIME (21):  Component start time
    CP_END_TIME (21):  Component end time
    CP_STATUS (251):  Component-reported status
    CC_INCARN_NO (23):  Incarnation Number
    CC_DESC_TEXT (251):  Component description

Se você incluir a opção show você poderá especificar quais as colunas você quer ver e em qual ordem elas irão ser mostradas:

srvrmgr> configure list comp show SV_NAME(31),CC_ALIAS(21),CC_NAME(76)

srvrmgr> configure list comp
        SV_NAME (31):  Server name
        CC_ALIAS (21):  Component alias
        CC_NAME (76):  Component name

srvrmgr> list comp

SV_NAME     CC_ALIAS              CC_NAME
----------  --------------------  ----------------------------------------
siebsrvdev  BusIntBatchMgr        Business Integration Batch Manager
siebsrvdev  BusIntMgr             Business Integration Manager
siebsrvdev  ClientAdmin           Client Administration
siebsrvdev  CommConfigMgr         Communications Configuration Manager
siebsrvdev  CommInboundMgr        Communications Inbound Manager
...
siebsrvdev  eSitesClinicalObjMgr  eSitesClinical Object Manager (PTB)

52 rows returned.

Agora ficou mais fácil ler!

Mas pode ser que você precise ter todas as colunas e se for o caso, o que fazer?

Aí que vem o truque sujo (até aonde eu sei) não documentado. Lhes apresento o comando set. Com ele você pode exibir ou alterar alguns parâmetros do ambiente do srvrmgr. Vamos ver as opções:

srvrmgr> set
username            sadmin*
service             (null)
enterprise          (null)
app server          (null)
compression         FALSE*
encryption          FALSE*
protocol            TCP/IP*
port                (null)*
cluster             (null)*
name server         (null)*
log filter          (null)
verbose             FALSE
batch               FALSE
header              TRUE
footer              TRUE
ColumnWidth         (null)
delimiter          

Não vou explicar aqui cada um destes parâmetros (até porque isto está documentado). A questão fica por conta do parâmetro ColumnWidth. Se você habilitar ele será possível definir o tamanho das colunas através do comando configure list.

srvrmgr> set ColumnWidth true

srvrmgr> set
username            sadmin*
service             (null)
enterprise          (null)
app server          (null)
compression         FALSE*
encryption          FALSE*
protocol            TCP/IP*
port                (null)*
cluster             (null)*
name server         (null)*
log filter          (null)
verbose             FALSE
batch               FALSE
header              TRUE
footer              TRUE
ColumnWidth         1
delimiter  

Pronto! Agora você pode definir o tamanho das colunas! Repare que no comando configure list você vê o nome da coluna e um número entre parênteses: esse número é o tamanho em caracteres da coluna. O comando abaixo de exemplo altera o tamanho de alguns campos do comando list comp para que nome das colunas não seja truncado:

srvrmgr> configure list comp show SV_NAME(31),CC_ALIAS(21),CC_NAME(76),CT_ALIAS(31),CG_ALIAS(31),CC_RUNMODE(31),CP_DISP_RUN_STATE(61),CP_NUM_RUN_TASKS(16),CP_MAX_TASKS(12),CP_ACTV_MTS_PROCS(17),CP_MAX_MTS_PROCS(16),CP_START_TIME(21),CP_END_TIME(21),CP_STATUS(251),CC_INCARN_NO(23),CC_DESC_TEXT(251)

Evitando ter que repetir este trabalho todo

Depois de configurar tantas coisas você deve ter pouca vontade de ter que digitar uma segunda vez isso tudo. para isto existe os comandos save preferences e load preferences. Esses comandos vão, respectivamente, gravar um arquivo de configuração no diretório aonde está localizado srvrmgr e depois carregá-lo. O nome do arquivo é por padrão ".Siebel_svrmgr.pref". Na realidade é um arquivo texto simples. Se depois de você fazer esta configuração você salvar o arquivo e resolver editá-lo, você verá exatamente isto:

configure list components show SV_NAME(31) , CC_ALIAS(21) , CC_NAME(76) , CT_ALIAS(31) , CG_ALIAS(31) , CC_RUNMODE(31) , CP_DISP_RUN_STATE(61) , CP_NUM_RUN_TASKS(16) , CP_MAX_TASKS(12) , CP_ACTV_MTS_PROCS(17) , CP_MAX_MTS_PROCS(16) , CP_START_TIME(21) , CP_END_TIME(21) , CP_STATUS(251) , CC_INCARN_NO(23) , CC_DESC_TEXT(251)

Realmente não é nenhuma mágica, mas funciona.

Conclusão

Talvez você esteja se perguntando para que serventia ter este trabalho todo. Bem, se você estiver escrevendo um parser dos comandos do srvrmgr (como eu estou fazendo aqui) isso é de grande valia!

Falando sério agora, ter a possibilidade de customizar o ambiente do programa para suas necessidades vai lhe ajudar bastante no seu trabalho, principalmente a ganhar agilidade para fazer as coisas. Verifique também a possibilidade de criar alias e salvá-los via save preferences, você vai ver que isso vai lhe ajudar bastante!