Páginas

domingo, 28 de outubro de 2012

[C++] Lista de argumentos com tamanho variável


Nem todas as linguagens de programação permitem criar sub-rotinas com o número variável de parâmetros.  Entretanto, C/C++ permitem a criação deste tipo de sub-rotina. Para isso, utiliza-se reticências (...) em um protótipo de uma função que pode receber um número variável de argumentos não importando seus tipos. Deve-se notar que as reticências devem ser colocadas no final da lista de argumentos. Macros e definições do cabeçalho de argumentos variáveis <cstdarg> são utilizados para se obter os recursos necessários para a construção deste tipo de função.

A função soma desenvolvida utiliza todas as definições de macros do cabeçalho <cstdarg>. O objeto lista, do tipo va_list, é utilizado pelas macros va_start, va_arg e va_end para processar a lista de argumentos da função soma.

Macros:
  • va_list: tipo utilizado para armazenar informações para as macros va_arg e va_end. É necessário declarar um objeto do tipo va_list para acessar os argumentos de uma lista de argumentos de tamanho variável.
  • va_start: macro chamada antes que seja possível acessar os argumentos da lista de tamanho variável. Esta macro inicializa o objeto declaro com va_list.
  • va_arg: esta macro é expandida para uma expressão de valor e tipo do próximo argumento da lista. Sempre que invocada, esta macro irá modificar o objeto declarado com va_list para que seja apontado para o próximo objeto da lista.
  • va_end: utilizada para facilitar o retorno de uma função cuja a lista de argumentos tenha sido referenciada por va_start.

Exemplo:


#include <iostream>
#include <cstdarg>

using std::cout;
using std::endl;

int soma(int, ...);

int main(int argc, char** argv) {

        int x = 1, y = 2, z = 3;

cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "z = " << z << endl;

cout << "A soma de x e y é: " << soma(2, x, y) << endl;
cout << "A soma de x, y e z é: " << soma(3, x, y, z) << endl;

return 0;
}

int soma(int i, ...) {

int total = 0;
va_list lista;

va_start(lista, i);

for (int j = 1; j <= i; j++)
total += va_arg(lista, int);

va_end(lista);

return total;
}

Resultado:
x = 1
y = 2
z = 3
A soma de x e y é: 3
A soma de x, y e z é: 6

É isso, divirtam-se.

segunda-feira, 15 de outubro de 2012

[Android] Adicionando botões dinamicamente na tela da aplicação.


Estava eu estudando um pouco de android (comecei a brincar disso esses dias) e queria colocar objetos diferentes na tela do meu aplicativo dependendo da ação realizada pelo usuário.

A ideia era que se o usuário pressionasse o botão 1 alguns objetos aparecessem na tela, mas se o botão 2 fosse pressionado, outros objetos aparecessem.

Fiquei lendo alguns tutoriais pra descobrir uma forma de fazer isso, mas não encontrei a resposta em um único lugar, por esta razão, depois de ler vários tutoriais e descobrir como fazer resolvi escrever este post.

A minha ideia foi criar dois frames, no primeiro frame haveriam 2 botões (botão 1 e botão 2 - bem criativo). Se o botão 1 fosse pressionado, apareceriam os botões 3 e 4 no frame 2. Caso fosse pressionado o botão 2, os botões 5, 6 e 7 apareceriam no frame 2.

Vejam, assim como foi feito com botões, poderiam ter sido utilizados outros objetos. É que fazer com botões era mais fácil e num precisava de muita criatividade, por isso optei por essa opção. (Na verdade, eu nem acho que tinha uma opção, mas isso não é assunto pra esse blog).

Pois bem, pra montar meu super projetinho foi utilizado o eclipse INDIGO (Xupa JUNO).

Inicialmente eu criei um projetinho android no eclipse com os seguintes passos:

File -> New -> Android Application Project

Tela New Android Application:

Application Name = BotoesInterativos
Project Name = BotoesInterativos
Package Name = com.example.botoesinterativos
Build SDK = Android 4.1 (API16)
Minimum Required SDK = API8: Android 2.2 (Froyo)

Clicar NEXT

Tela Create Activity:

Selecionar o checkbox 'Create Activity'
Selecionar a opção BlankActivity

Clicar NEXT

Tela New Blank Activity

Activity Name = MainActivity
Layout_name = activity_main
Navigation Type = None
Title = MainActivity

Pronto, uma vez criado o projeto, iremos alterar o arquivo activity_main.xml que se encontra no diretório res/layout. Este arquivo tem o seguinte formato.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/frameLayout1"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
              android:background="#ABABAB">
   
            <Button
                     android:id="@+id/botao1"
                     android:layout_width="90dp"
                     android:layout_height="35dp"
                     android:text="Botão 1"
                     android:textSize="10sp"/>
            <Button
                     android:id="@+id/botao2"
                     android:layout_width="90dp"
                     android:layout_height="35dp"
                     android:text="Botão 2"
                     android:layout_toRightOf="@+id/botao1"
                     android:textSize="10sp"
                     android:layout_centerHorizontal="true"/>
       </RelativeLayout>
      
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:layout_below="@+id/frameLayout1"
        android:id="@+id/frameLayout2"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:background="#ABABAB">

              <TableLayout
            android:id="@+id/tableLayoutFrame2"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scrollbars="horizontal"
            android:shrinkColumns="0">
           
              </TableLayout>
          
    </RelativeLayout>
</RelativeLayout>

Observe que foram utilizados 2 RelativeLayout. No primeiro, existem os botões 1 e 2, enquanto que no segundo existe um TableLayout que será utilizado para colocarmos os demais botões dinamicamente.

Em seguida, alteramos o arquivo MainActitivity.java para ficar da seguinte forma:

package com.example.botoesinterativos;

import android.os.Bundle;
import android.app.Activity;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        final TableRow tr = new TableRow(this);
       
        //Botões para opção botão 1
        final Button botao3 = new Button(this);
        final Button botao4 = new Button(this);
       
        botao3.setText("Botão 3");
        botao4.setText("Botão 4");
       
        botao3.setTextSize(10);
        botao4.setTextSize(10);
       
        botao3.setWidth(135);
        botao4.setWidth(135);
       
        botao3.setMinimumHeight(30);
        botao4.setMinimumHeight(30);
       
        botao3.setHeight(35);
        botao4.setHeight(35);
       
        //Botões para opção botão 2
        final Button botao5 = new Button(this);
        final Button botao6 = new Button(this);
        final Button botao7 = new Button(this);
       
        botao5.setText("Botão 5");
        botao6.setText("Botão 6");
        botao7.setText("Botão 7");
       
        botao5.setTextSize(10);
        botao6.setTextSize(10);
        botao7.setTextSize(10);
       
        botao5.setWidth(135);
        botao6.setWidth(135);
        botao7.setWidth(135);
       
        botao5.setMinimumHeight(30);
        botao6.setMinimumHeight(30);
        botao7.setMinimumHeight(30);
       
        botao5.setHeight(35);
        botao6.setHeight(35);
        botao7.setHeight(35);
       
        final Button botao1 = (Button) findViewById(R.id.botao1);
        botao1.setOnClickListener(new View.OnClickListener() {
                    
                     public void onClick(View v) {
                          
                           //Obtém o TableLayout
                           TableLayout ll = (TableLayout) findViewById(R.id.tableLayoutFrame2);
                          
                           //Limpa as views criadas anteriormente
                           tr.removeAllViews();
                           ll.removeAllViews();
                          
                           //Adiciona os botões à tabela
                           tr.addView(botao3);
                           tr.addView(botao4);
                          
                           int lHeight = RelativeLayout.LayoutParams.FILL_PARENT;
                           int lWidth = RelativeLayout.LayoutParams.WRAP_CONTENT;

                           //Adiciona a tabela ao TableLayout
                           ll.addView(tr, new RelativeLayout.LayoutParams(lHeight, lWidth));
                     }
              });
       
        final Button botao2 = (Button) findViewById(R.id.botao2);
        botao2.setOnClickListener(new View.OnClickListener() {
                    
                     public void onClick(View v) {
                          
                           //Obtém o TableLayout
                           TableLayout ll = (TableLayout) findViewById(R.id.tableLayoutFrame2);
                          
                           //Limpa as views criadas anteriormente
                           tr.removeAllViews();
                           ll.removeAllViews();
                          
                           //Adiciona os botões à tabela
                           tr.addView(botao5);
                           tr.addView(botao6);
                           tr.addView(botao7);
                          
                           int lHeight = RelativeLayout.LayoutParams.FILL_PARENT;
                           int lWidth = RelativeLayout.LayoutParams.WRAP_CONTENT;

                           //Adiciona a tabela ao TableLayout
                           ll.addView(tr, new RelativeLayout.LayoutParams(lHeight, lWidth));
                     }
              });
       
    }   
}


Note que nesta classe é criado um objeto tr (TableRow). Cada objeto inserido neste TableRow será uma coluna da tabela. Em seguida, são criados os botões 3, 4, 5, 6 e 7. O próximo passo é criar os eventos que serão utilizados pelos botões 1 e 2 para que os botões 3, 4, 5, 6 e 7 possam aparecer na tela.

As figuras abaixo mostram como ficou a tela da aplicação. Na primeira figura, nenhum botão foi pressionado. Na segunda, o botão 1 foi pressionado e apareceram os botões 3 e 4. Na última figura, o botão 2 foi pressionado e apareceram os botões 5, 6 e 7.






Viram só, simples como a vida tem que ser.

[Linux] Acessando a wireless com criptografia WPA pelo terminal do Linux.

Uma boa ferramenta para ajudar na conexão wireless pelo terminal do Linux é o wpa_supplicant. Este utilitário ajuda a configurar a rede com criptografia WPA de um modo simples.


Para utilizá-lo é preciso criar (ou editar se já existir) um arquivo em /etc, chamado wpa_supplican.conf (/etc/wpa_supplican.conf); para isso, é necessário ser super usuário (sudo no ubuntu e afins e su no Slackware).

Abra o arquivo e adicone as linhas ao final do arquivo:

network={
        scan_ssid=0
        ssid="MyNetwork"
        psk="MyPass"
        proto=WPA RSN
        key_mgmt=WPA-PSK WPA-EAP
        pairwise=CCMP TKIP
        group=CCMP TKIP
}

Onde:
                    MyNetwork é o nome da rede em que vc quer acesso
                    MyPass é a chave utilizada para ter acesso à rede

Pronto; para conectar, basta executar no terminal:

wpa_suppliant -Dwext -iwlan0 -c /etc/wpa_suppliant.conf &

Para obter um endereço de rede (no caso de usar dhcp), execute:

dhcpcd -d wlan0

Lembre-se:
  • Estou assumindo que sua interface wireless está definida em wlan0
  • Certifique-se que a interface wlan0 está ativa. Para isso execute o comando ifconfig -a; deverá aparecer a interface wlan0. Caso nao veja a interface, ative-a com ifconfig wlan0 up e volte a executar os comandos acima.
 Ao final, deve-se obter alguma coisa do tipo:

wlan0     Link encap:Ethernet  HWaddr 00:02:72:9b:a7:e0 
          inet addr:192.168.1.107  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::202:72ff:fe9b:a7e0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:339700 errors:0 dropped:0 overruns:0 frame:0
          TX packets:208785 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:400332866 (400.3 MB)  TX bytes:27863221 (27.8 MB)



Quaquer dúvida, pergunte!

[Oracle] Estruturas de Armazenamento - Tablespaces e Arquivos de Dados

A forma de armazenamento em um banco de dados Oracle pode ser analisada pelo lado físico ou lógico. Analisando de forma física, os componentes de armazenamento são vistos como arquivos  de dados (nível do sistema operacional). Já o armazenamento lógico é a forma como o Oracle gerencia, de forma interna, os objetos que estão armazenados no banco de dados.

Considerando o modelo de armazenamento utilizado pelo Oracle, temos que:
  1. A base de dados deve ser formada por um ou mais tablespaces, sendo que todo tablespace deve pertencer a apenas um banco de dados.
  2. Todo tablespace é formado por um ou mais arquivos de dados e cada arquivo de dados pertence a somente um tablespace.
  3. O arquivo de dados é formado por um ou mais blocos do SO. Cada bloco do SO pode pertencer a apenas um arquivo de dados.
  4. O tablespace é formado por um segmento ou mais, sendo que o segmento deve existir em apenas um tablespace.
  5. Todo segmento é formado por extensões. Cada segmento pode existir em somente um tablespace.
  6. A extensão é formada de um ou mais blocos do Oracle. Cada um desses blocos pode pertencer a somente uma extensão.
  7. Cada extensão estã localizada em um arquivo de dados. Um espaço no arquivo de dados pode ser alocado na forma de uma ou várias extensões.
  8. Todo bloco do Oracle constitui de um ou mais blocos do SO.
O esquema descrito acima pode ser visto na seguinte figura:



Estruturas de Armazenamento Físicas

Chamamos de estrutura física aquilo que o sistema operacional “vê” quando “olha” para uma base de dados Oracle, pois trata-se de um conjunto de arquivos de dados. Também pode-se utilizar partições de um disco que não está sendo gerenciada pelo SO para armazenar os arquivos de dados, entretanto, isso introduz certa complexidade (e eu num manjo nada disso). Também é possível que o Oracle gerencie ele mesmo o armazenamento da estrutura física utilizando ASM (Automated Storage Management), nestes dois últimos casos o SO não está envolvido.

Arquivos de Dados Oracle

Quando um banco de dados é criado, também é criada uma série de arquivos para armazenar o dicionário de dados e os dados do tablespace SYSAUX, além de outros tablespaces que o DBA tenha resolvido criar. Estes arquivos de dados consistem de um cabeçalho que o identifica como parte de um banco de dados Oracle, de informações sobre a qual tablespace ele pertence e qual o último checkpoint realizado. O restante do arquivo é formado por extenões e espaço livre.

Blocos do Sistema Operacional

São a unidade mínima cuja a alocação é possível para o sistema de arquivos. Os seus tamanhos podem variar dependendo do sistema de arquivos, sendo que a maioria dos sistema permite configurar o tamanho dos blocos durante a formatação do disco. Por questão de desempenho é aconselhável manter o tamanho dos blocos do sistema operacional igual ao tamanho dos blocos Oracle. Obs: é possível criar tablespaces com tamanhos de blocos diferentes dentro do mesmo banco de dados.

Estruturas de Armazenamento Lógicas

A estrutura lógica é formada pelos tablespaces, segmentos e extensões. No banco de dados Oracle são necessários pelo menos 3 tablespaces (de preferência mais) considerando o Oracle 10g. Nas versões anteriores eram necessário apenas 1 tablespace.

Tablespaces

É a maior estrutura dentro de um banco de dados e todo banco de dados Oracle 10g precisa de pelo menos três tablespaces:
  • SYSTEM: Utilizado para armazenar o dicionário de dados além dos objetos do esquema SYS.
  • SYSAUX: Armazena os objetos que não são do usuário SYS, mas que são essenciais ao funcionamento do banco de dados. Este tablespace é utilizado, por exemplo, para armazenar estatísticas do banco de dados.
  • UNDO: É utilizado para armazenar as informações de UNDO. Essas informaçõe permitem que usuários leiam linhas de uma tabela, de forma consistente, enquanto elas  estejam sendo modificadas.
Quando um banco de dados é criado com o DBCA (Assistente de Configuração de Banco de Dados – sigla em inglês), além dos tablespaces acima, também são criados os tablespaces TEMP e USERS. Nota o tablespace de UNDO é criado com o nome UNDOTBS1.
  • TEMP: Utilizado para armazenar dados temporários do banco de dados, por exemplo, conteúdo de tabelas temporárias. Além disso, é utilizado como espaço para classificação de dados. Embora não seja um tablespace obrigatório, é altamente recomendado a sua criação.
  • USERS: É utilizado para armazenar os dados dos usuários. Este é o tablespace padrão que pode ser utilizado pelos usuários do banco de dados (exceto SYS e SYSTEM).
Os tablespaces podem ser classificados como SYSTEM ou não-SYSTEM: No Oracle 10g, apenas os tablespaces SYSTEM e SYSAUX são considerados tablespaces SYSTEM, os demais são não-SYSTEM.

Segmentos

Os segmentos são alocados dentro dos tablespaces. Um segmento nada mais é do que um objeto do banco de dados que requer armazenamento, por exemplo, um índice ou uma tabela. É permitido criar vários tipos diferentes de segmentos, sendo que a view DBA_SEGMENTS exibe todos os segmentos criados no banco.

SELECT DISTINCT segment_type FROM DBA_SEGMENTS;

Extensões

São formadas por blocos contíguos, podendo ser gerenciadas de forma automática ou manual. Quando é alocado espaço para criação de segmentos em um tablespace, é também alocada uma extensão de cada vez (o segmento é formado por uma ou mais extensões.) As extensões podem ser gerenciadas de forma local (recomendado) ou no dicionário de dados (existente por questão de compatibilidade com versões anteriores ao Oracle 10g).

Blocos do Banco de Dados

São as menores unidades de E/S do banco de dados. Isto significa que quando o banco precisa ler dados do disco, todo o bloco onde o dado está contido deve ser lido. A mesma coisa ocorre na escrita mesmo que uma única linha de um bloco tenha sido alterada. Nota: não é possível alterar o tamanho dos blocos de dados de um tablespace depois dele ter sido criado.

terça-feira, 9 de outubro de 2012

[Android] Configurando o ambiente no Eclipse Juno

Como bom usuário de linux, tento manter meu sistema sempre atualizado.
Sempre da certo de atualizar o sistema? Claro que sim! Tudo funciona como antes? Claro que não.

Vão dizer.. lá vem o noob novato falando de coisas que não entende.. Pra esses tenho somente uma pergunta: quantas vezes os upgrades de versão do ubuntu funcionaram? Claro que nenhuma kkk... Problemas com o SO a parte....

Bem, dessa vez foi o Eclipse que me pegou de surpresa.
Apesar de ler em vários lugares as pessoas postando coisas sobre o mesmo problema que eu tive (não abria) e as possíveis correções que podiam recuperá-lo, decidi abrir mão do antigo e bom Eclipse Indigo e migrar para o novo: Eclipse JUNO!

Novas versões sempre me deixam animado!
Como decidi abandonar o antigo (Eclipse Galileo Indigo) que estava utilizando, parti do zero e comecei a instalar os plugins que utilizava: CDT pra C/C++ e os do Android.

Bom, de cara fui ao oráculo e perguntei como instalava tudo isso, apesar de achar que era do mesmo modo como no antigo. O CDT sempre do mesmo jeito, já está lá nos repositorios do JUNO.

Com o ADT não quiz arriscar. Encontrei esse ótimo tutorial no Google Developers: https://developers.google.com/eclipse/docs/install-eclipse-4.2

Lá mostra como instalar tudo.

Porém, se não funcionar (se baixou a versão clássica não vai funcionar, pois o plugin do Android precisa de um pacote que se chama WST Server Adapters) , instale o WST;

Vá em:

Help -> Install New Software.

Selecione os repositorios do JUNO:

Agora clique em:

->Web, XML, Java,.. (é um dos últimos, isso se não for o último)

Selecione o pacote WST Server Adapters e siga o bom e tradicional NNF (Next, Next e Finish). Não esqueça de aceitar a licença.







E pronto. O Plugin deve funcionar.
Qualquer dúvida, fique a vontade para perguntar!!

Enjoy!

[Objective-C] Uso de selectors

Objective-C é uma linguagem feita para tornar as coisas simples. Tão simples que para quem não está acostumado pode soar como (coxa) excessiva.

Sabe todo aquele blah blah blah de alta coesão e baixo acoplamento? Então, várias features nativas do Objective-C podem te ajudar a alcançar estas diretrizes da Engenharia de Software, no que diz respeito à Programação Orientada a Objetos (POO).

Neste post vamos falar sobre uma facilidade provida pela linguagem Obj-C, que são os selectors (seletores, na tradução livre).

Imagine que você cria um simples programinha com uma dezena de classes. Dentre essas classes temos a classe Formulário que é uma classe ligada a modelagem do sistema e sem ligação direta com o negócio e uma outra classe Carro que é ligada ao negócio.

Por "coincidência" as duas classes tem o método
-(void)setVisibility:(bool)visibility;
o qual permite esconder ou mostrar determinado objeto das classes. Até aí tudo bem, são classes distintas que não compartilham nenhuma herança (i.e. superclasses e interfaces protocolos).

Mas o que o Obj-C faz quando compila estas classes é o grande pulo do gato: O compilador gera um identificar único para cada método de uma classe. Este identificador do método é gerado baseado no seu nome e nos parâmetros que ele recebe, mas não leva em consideração a classe em que o método está inserido.

Neste caso, o compilador vai gerar o mesmo identificador do método para ambas as classes. Este identificador é conhecido como selector.

Neste momento o leitor indaga:
- Tá bom, eu tenho dois métodos em classes diferentes que tem o mesmo identificador, mas pra quê isso vai ser útil???
Respondo:
-Não sejais apressado, pequeno gafanhoto.

Em Obj-C é possível executar um método de um objeto através de seu seletor, ou seja, você não precisa conhecer a classe, ou a interface o protocolo que uma classe "implementa" para conseguir realizar uma invocação. Tudo que você precisa é saber qual o seletor daquele método.
Para o nosso exemplo teríamos o seguinte seletor:
SEL visibilitySelector = @selector(setVisibility:)
Agora, voltando ao exemplo, imaginemos que uma classe é responsável por esconder ou tornar visível os objetos que são apresentados, de acordo com o perfil de autenticação do usuário na aplicação. Essa classe não precisa de conhecer muita coisa, basta apenas ser capaz de executar o seletor nos objetos corretos.

Aqui vai um outro truque, para executar um seletor que recebe parâmetros, nos utilizamos a diretiva
-(id)performSelector:(SEL)sel withObject:(id)obj
, mas no nosso exemplo o parâmetro recebido pelo método é um tipo primitivo (booleano). Neste caso devemos encapsulá-lo em uma classe que possa ser reconhecida pelo método como um booleano.

A forma mais comum, para o caso do booleano, é encapsular em um número inteiro (NSNumber):
bool myBool = true; 
NSNumber *passedValue = [NSNumber numberWithBool:myBool];

Aí sim, podemos executar o seletor, passando o valor booleano dentro do objeto da classe NSNumber. Trabalhando desta forma conseguimos fazer com que a classe que faz a gestão da visibilidade dos objetos não seja acoplada com outras classes ou protocolos, tornado a vida do programador mais fácil.

PS: Tá bom, com reflection eu também consigo fazer alguma coisa parecida em java, apesar de ser muito mais burocrático.
PS2: Se ficou alguma coisa não inteligível é porque acabou meu café.

segunda-feira, 8 de outubro de 2012

[Oracle] Arquitetura Física


Um banco de dados Oracle é composto por três tipos de arquivos: arquivos de controle, arquivos de dados e arquivos de redo log on-line.
  • Arquivos de controle: Estes arquivos possuem os metadados acerca do banco de dados, sendo que sem estes arquivos não é possível abrir os arquivos da base de dados.  Estes arquivos possuem informações sobre a estrutura física do banco de dados e podem ser multiplexados (em pelo menos 3 lugares diferentes)para evitar perdas. Quando uma instância é iniciada e o banco de dados é montado, o arquivo de controle é lido. Nesses arquivos contêm as especificações dos demais arquivos que formam o banco de dados. Desta forma, sempre que mais arquivos são adicionados à base de dados, os arquivos de controle são atualizados.
  • Arquivos de dados: Estes arquivos possuem os dados do banco propriamente dito. Os tablespaces de um banco de dados são unidades lógicas de armazenamento, sendo que o banco de dados está dividido um ou mais tablespaces e para cada tablespace é criado um ou mais arquivos de dados. OBS: os arquivos de dados pertencem a apenas um tablespace. 
  • Arquivos de redo log on-line: São utilizados para registrar todas as alterações realizadas no banco de dados por meio de transações e de ações internas do servidor. Eles são utilizados para proteger a integridade do banco quando ocorrem falhas de sistema (interrupção de energia, falhas nos discos, etc). Assim como os arquivos de controle, os arquivos de redo log on-line devem ser multiplexados para evitar perdas. Um grupo de redo log é formado por um arquivo de redo log e de suas cópias multiplexadas, sendo que cada cópia é idêntica. O processo responsável por gravar dados nos arquivos de redo log é o LGWR (Log Writer). Esse processo grava dados no grupo de redo log até preencher o arquivo ou até que uma operação alternância de log seja solicitada. Desta forma, os dados vão sendo gravados nos grupos de redo log de forma circular.
Além dos três arquivos mencionados acima, existem outros arquivos importantes, mas que não fazem parte oficialmente de um banco de dados Oracle.
  • Arquivo de parâmetros: É utilizado para definir como será a configuração da instância quando ela for iniciada.
  • Arquivo de senha: Utilizado para que usuários se conectem remotamente ao banco de dados e possam executar tarefas administrativas.
  • Arquivos de log de arquivamento: Possuem o histórico de redo log gerado pela instância. Utilizando esses arquivos em conjunto com um backup do banco de dados, pode-se recuperar um arquivo de dados perdido. 
OBS: Estas informações são baseadas no material oficial da Oracle - Banco de Dados Oracle 10g: Workshop de Administração I.


sexta-feira, 5 de outubro de 2012

[Oracle] Autenticação

Conectando-se com um Privilégio Apropriado

Quando conectado a uma instância, os usuários normais não podem nem inicializar nem finalizar um banco de dados, pois este tipo de usuário é autenticado considerando o dicionário de dados. Desta forma, é impossível que este usuário inicialize ou crie um banco de dados, pois o dicionário de dados não está acessível até que o banco de dados tenha sido aberto.
Para inicializar/finalizar um banco de dados é necessário algum tipo de autenticação externa. Esta autenticação pode ser efetuada pelo sistema operacional ou por uma combinação usuário/senha existente no arquivo de senhas (externo).
Quando se conetar à instância, você informa a forma de autenticação apropriada no comando CONNECT através do seu processo de usuário.
As possíveis formas de conexão são:
  • connect user/pass[@db]
  • connect user/pass[@db] as sysdba
  • connect user/pass[@db] as sysoper
  • connect / as sysdba
  • connect / as sysoper
No primeiro exemplo acima é utilizada a autenticação normal via dicionário de dados. Neste caso, o banco de dados precisa estar aberto e o usuário conectado (não importa quem seja) não pode emitir comandos startup ou shutdown.
Nos dois próximos exemplos o Oracle irá até o arquivo de senha para validar a combinação usuário e senha.
A autenticação via sistema operacional está exemplificada nos dois últimos exemplos. Nestes casos, o Oracle irá consultar o SO subjacente para verificar se o usuário que está executando o SQL*Plus é membro do grupo do SO que possui a propriedade do software Oracle. Se a verificação obtiver sucesso o usuário será logado como SYSDBA ou SYSOPER.
Um usuário que se conecte ao banco com qualquer uma das quatro últimas opções poderá emitir comandos startup ou shutdown e conectar-se sem se importar com o estado do banco de dados (aberto ou não, por exemplo).
Observe que nos três primeiros exemplos foi fornecido uma string de conexão com o banco de dados. Isso é necessário se a conexão for realizada através de uma rede. Obviamente, para a autenticação via SO isto não é necessário pois o usuário deve estar logado na máquina onde reside o servidor Oracle.

SYSOPER e SYSDBA

SYSOPER e SYSDBA são privilégios que possuem capacidades especiais e só são habilitados caso o usuário tenha sido autenticado por um método externo. Um usuário conectado com este privilégio pode emitir os seguintes comandos:
  • STARTUP
  • SHUTDOWN
  • ALTER DATABASE [MOUNT | OPEN | CLOSE | DISMOUNT]
  • ALTER [DATABASE | TABLESPACE] [BEGIN | END] BACKUP
  • RECOVER
Já o privilégio SYSDBA permite emitir todos os comandos acima além de adicionar a capacidade de criar um banco de dados, fazer uma recuperação incompleta e criar outros usuários SYSOPER e SYSDBA.