25 noiembrie 2011

Aplicatie Android pentru vreme

Aplicatia se foloseste de serviciul de la Google pentru aflarea vremii.
Codul se afla aici: http://code.google.com/p/weather-application-tg2011/








Update 2013:
Google a închis serviciul pentru aflarea vremii în timp real.
De aceea am modificat programul folosind API-ul de la OpenWeatherMap, codul se află aici

22 noiembrie 2011

Cajun Meet preview




O aplicatie pentru schimbul de carti de vizita intre studentii unei universitati.
Aplicatia realizeaza schimbul de carti de vizita prin wifi si creeaza o mica baza de date a contactelor obtinute.
Pentru asa-zisa comunicatie prin wifi, se foloseste un mediu partajat: Google SpreadSheet.

Many many thanks to gss-lib fara de care acest proiect nu ar fi putut fi implementat chiar atat de usor.

Simularea protocolului MESI in C


<--- schema pentru protocolul Mesi cu invalidare pentru memoria cache de tip "write back"

MESI = initialele celor 4 stari ale memoriilor cache asociate unor procesoare (Modified, Exclusive, Shared, Invalid)

Invalid -> la inceputul rularii toate cache-urile sunt "I" sau atunci cand un procesor face scriere pe propriul cache, rezulta celelalte cache-uri devin "I"

Exclusive -> cand se aduc datele din memoria principala intr-una dintre memoriile cache (celelalte cache-uri fiind pe starea "I")

Modified -> dupa fiecare write al unui procesor, memoria cache asociata devine "M" (si restul "I")

Shared -> dupa ce o memorie cache isi imparte datele cu o alta, indiferent cum erau inainte, ambele ajung in starea "S"

Simularea de mai jos este relativ simplista, nu afiseaza actiunea pe magistrala (BusRd, Flush, etc) si nici informatii despre sursa de date, ci doar starile succesive ale cache-urile asociate procesoarelor.

#include "stdio.h"
#include "stdlib.h"
#define N 3

char s[N];
int mem[N*4] = {1,0,1,0,0,1,1,0,1,1,0,1};
int cache[N][N], n;

void operatie (int p, char *op) {

int i;

if (*op == 'w') {
s[p] = 'M';
for (i=0; i < N; i++)
if (i != p)
s[i] = 'I';
goto afisare;
}
if (*op == 'r') {
if (s[p] == 'M' || s[p] == 'E')
goto afisare;
if (s[p] == 'I') {
int flag = 1;
for (i=0; i < N; i++)
if (s[i] != 'I')
flag = 0;
if (flag == 1) {
s[p] = 'E';
goto afisare;
}
for (i=0; i < N; i++)
if (s[i] == 'E' || s[i] == 'S' || s[i] == 'M')
s[i] = 'S';
s[p] = 'S';
}
goto afisare;
}
afisare:
for (i=0; i < N; i++)
printf("%c ", s[i]);
printf("\n");
}

int main () {

char *op = (char*) malloc (sizeof (char));
int i, j;
for (i=0; i < N; i++) {
for (j=0; j < N; j++)
cache[i][j] = 0;
s[i] = 'I';
}
printf("n=");
scanf("%d", &n);
printf("initial\n");
for (i=0; i < N; i++)
printf("%c ", s[i]);
printf("\n");
for (i=0; i < n; i++) {
int proc;
printf("P=");
scanf ("%d", &proc);
printf("op=");
scanf ("%s", op);
operatie (proc-1, op);
}

return 0;

}

Pentru test se poate folosi secventa:

Se citesc: n (numarul de operatii, 8) , P (indicele procesorului, 1..3) si operatia (r/w)
Sunt afisate cele N = 3 stari dupa fiecare pas.

Cautare paralela in OpenMP

Mai demult scriam o postare despre cautarea in paralel in Java, folosind thread-uri. De data aceasta am scris si in OpenMP, si este mult mai intuitiv si usor de inteles decat inainte.

De la tastatura se dau: n (nr de elemente), x (numarul cautat) si p (numarul de procesoare); se genereaza apoi n numere naturale intr-un vector care se ordoneaza folosind quicksort si pe care se va face cautarea paralela. Pozitia afisata reprezinta pozitia in acest vector ordonat.

#include "omp.h"
#include "stdio.h"
#include "stdlib.h"

int min (int a, int b) {

if (a < b)
return a;
return b;
}

int comp (const void * a,const void * b) {

if (*((int*)a)==*((int*)b))
return 0;
if (*((int*)a) < *((int*)b))
return -1;
return 1;
}

void cautare (int x, int a[], int n, int left, int right, int p) {

int pas = (right-left)/p+1;
int i, aux = -1;

if(left == right && a[left]==x)
return ;

#pragma omp parallel private(i) num_threads(p)
{
#pragma omp for
for(i = left; i<=right; i+=pas) {

int tid = omp_get_thread_num();
int next = min (n-1, i+pas-1);

if(a[i]<=x && x <= a[next]) {
aux = i;
if (i != next)
printf ("Thread %d a gasit: intre pozitiile %d si %d\n", tid, i, next);
else
printf ("Thread %d a gasit pozitia = %d\n", tid, i);
}
}
}
if(aux >= 0)
cautare (x,a,n,aux,aux+pas-1,p);
else
printf ("Element inexistent\n");
}

int main() {

int *a, n, i, p, x;

unsigned int iseed = (unsigned int)time(NULL);
srand (iseed);

printf ("n=");
scanf ("%d", &n);

a = (int *)malloc (n*sizeof(int));

for (i=0; i < n; i++)
a[i] = rand () % 1000;

// sortare a
qsort((void*)a, n, sizeof(int), comp);
printf ("Multime: {");
for (i=0; i < n-1; i++)
printf ("%d, " , a[i]);
printf ("%d}\n", a[n-1]);

printf ("x=");
scanf ("%d", &x);
printf ("p=");
scanf ("%d", &p);

cautare (x,a,n,0,n-1,p);

return 0;
}

18 noiembrie 2011

Proceduri PL/SQL

Arhiva conține rezolvări pentru exercițiile următoare:
(pe un tabel studenti cu câmpuri pentru matricol, nume, grupa, medie, bursa)

1. procedură nestocată cu parametru un număr fond_pentru_burse care va seta bursele studenților cu media > 7. Bursele sunt proporționale cu media, fondul trebuie consumat integral.
2. procedură nestocată care calculează pentru o grupă dată ca parametru: nr de studenți, media mediilor și suma burselor acordate. Apelată pentru toate grupele din tabelă
3. procedură stocată pe server ce include un cursor explicit, primește ca parametri 2 numere: medie și bonus. Iterează pe mai mulți studenți cu media > medie și adaugă bonusul la valoarea bursei lor.

Simulare CW-PRAM in MPI

Următorul program simulează cererile de scriere a 4 procesoare conectate la o memoria partajată. Conform logicii descrise în pdf [1] și a priorității procesoarelor, dispozitivul de control al memoriei poate îndeplini cererea și scrie în memoria partajată la o anumită adresă, sau nu.
Pentru comunicațiile între procesoare și dispozitivul de control s-au folosit operațiile de send/receive ale MPI-ului.

[1] arhiva se poate descărca de aici

09 noiembrie 2011

Cursoare in PL/SQL

Practic, intr-un cursor se stocheaza rezultatul unei interogari. Prin el se pot itera mai usor rezultatele, rand cu rand.

Exemple...
Intr-un tabel "student" cu coloanele [ matricol | nume | grupa | medie | bursa | obs ] vrem sa:
1) parcurgem lista de studenti si sa afisam studentii cu media > media grupei (folosind un cursor, cu instructiunea FETCH)
2) actualizam bursa studentilor cu media > 7, dupa formula bursa=media*100, plus bonusuri pentru "sef_grupa" (500) sau "sef_promotie" (1000)
3) listam toti studentii dintr-o grupa dupa bursa, descrescator, cu grupa citita de la tst si data la parametru pt cursor. Listarea cuprinde: [ Nume | Grupa | Medie | Bursa | Poz. in grupa | Poz. in facultate ]

Rezolvari...

1)

set serveroutput on;

declare
CURSOR my_cursor IS
select s.nume, s.grupa, s.medie
from student s
where s.medie > (select avg(medie) from student where s.grupa=grupa group by grupa);
var my_cursor%ROWTYPE;

BEGIN

OPEN my_cursor;
dbms_output.put_line(rpad('Nume',10,' ') || ' ' || rpad('Grupa', 5, ' ') || ' ' || rpad('Medie',5, ' '));

LOOP
FETCH my_cursor into var;
EXIT when my_cursor%NOTFOUND;

dbms_output.put_line (rpad(var.nume,10,' ') || rpad(var.grupa, 5, ' ') || ' ' || rpad(var.medie,5, ' '));

END LOOP;

CLOSE my_cursor;
END;
/

-------------------------------------------------------------------------------

2)

declare
CURSOR my_cursor IS
select matricol, obs
from student
where medie > 7;
var my_cursor%ROWTYPE;
adaos number:=0;

BEGIN
FOR var IN my_cursor
LOOP
EXIT WHEN my_cursor%NOTFOUND;

adaos := 0;
IF var.obs = 'sef_grupa' THEN adaos := 500; END IF;
IF var.obs = 'sef_promotie' THEN adaos := 1000; END IF;

UPDATE student SET bursa=medie*100+adaos WHERE var.matricol=matricol;

END LOOP;
END;
/

------------------------------------------------------------------------

3) (nu foarte eficient)

set serveroutput on;

declare
CURSOR myc (p_grupa varchar2) IS
select matricol,nume,grupa, bursa,medie
from student
where grupa=p_grupa
order by bursa DESC;
var myc%ROWTYPE;

CURSOR cursor2 IS
select matricol
from student
order by bursa DESC;
var2 cursor2%ROWTYPE;

poz_grupa number:=1;
poz_fac number:=0;
contor number:=1;
param varchar2(5);

BEGIN
dbms_output.put_line(rpad('Nume', 20, ' ') || ' ' || rpad('Grupa', 6, ' ') || ' ' || rpad('Bursa',6, ' ') || ' ' || rpad('Medie', 7, ' ') || rpad('Poz grupa',9,' ') || ' ' || rpad('Poz fac', 7, ' '));
param := &readparam;
FOR var IN myc(param)
LOOP
EXIT WHEN myc%NOTFOUND;

contor:=1;
FOR var2 IN cursor2
LOOP

IF var2.matricol = var.matricol THEN poz_fac := contor; END IF;
contor:= contor+1;

EXIT WHEN cursor2%NOTFOUND;
END LOOP;

dbms_output.put_line(rpad(var.nume,20, ' ') || ' ' || rpad(var.grupa, 6, ' ') || ' ' || rpad(var.bursa, 6, ' ') || ' ' || rpad(var.medie, 7, ' ') || ' ' || rpad(poz_grupa, 9, ' ') || ' ' || rpad(poz_fac, 7, ' '));
poz_grupa:=poz_grupa+1;
END LOOP;
END;
/

08 noiembrie 2011

Java RMI

How to make it work:

1) adaugarea in variabila de mediu PATH a caii sdk-ului pt java, daca nu exista deja:
C:\ProgramFiles\Java\jdk1.7.0\bin

2) pornire RMI cu:
start rmiregistry 1099
1099 reprezinta portul.

3) crearea fisierelor de policy (cu permisiuni de accesare) atat pt client cat si pt server:

grant codebase "file:///C:\\Users\\anna\\Desktop\\lab5\\Eclipse\\ProgramareClient\\-" {
permission java.security.AllPermission;
};

grant codebase "file:///C:\\Users\\anna\\Desktop\\lab5\\Eclipse\\ProgramareServer\\-" {
permission java.security.AllPermission;
};

unde calea trebuie sa duca la intreg folderul clientului/serverului, pentru a se putea accesa orice resursa de acolo. Fisierul numit "policy" se afla si el tot in acest folder.
Atentie la backslash - trebuie dublat.

4) In Eclipse - in Run configurations - Arguments, atat pt server cat si pt client se adauga (daca exista o astfel de arhiva jar):

server:
-classpath .;programare.jar -Djava.rmi.server.codebase=file:///C:\Users\anna\Desktop\lab5\Eclipse\ProgramareServer\programare.jar -Djava.rmi.server.hostname=localhost -Djava.security.policy=policy
Proprietatea java.rmi.server.codebase specificã locatia de unde pot fi descãrcate definitii pentru clasele provenind de la server.
Proprietatea java.rmi.hostname specificã numele masinii sau adresa care urmeazã a fi completatã în obiectele de tip ciot care vor fi exportate.

client: asemanator, dar fara hostname

-classpath .;programare.jar -Djava.rmi.server.codebase=file:///C:\Users\anna\Desktop\lab5\Eclipse\ProgramareClient\programare.jar -Djava.security.policy=policy

Aici, "programare.jar" contine definitia obiectelor transmise intre client si server (= obiecte serializabile).

------

Cu aceste configuratii realizate, puteti testa un mic program de gestiune a unui orar, in care clientul (student) poate sa rezerve un interval de timp in intervalele specificate in "orar.txt" , de exemplu spre a-i prezenta ceva profesorului. Serverul raspunde cu "da"/"nu" si in functie de asta face rezervarea in fisierul "rezervari.txt". Ulterior, folosind acelasi id cu care a trimis cerere pentru un interval de timp, clientul poate sa renunte la rezervare.

03 noiembrie 2011

Simularea unei retele omega

O retea omega este construita din m=log2(N) retele de conexiune "shuffle" cascadate.
O retea de dimensiune n*n contine (n/2)log(n) comutatoare, deci are complexitate de O(n*log(n)) < O(n^2) cat are o retea crossbar.
Programul atasat simuleaza traseul fiecarei conexiuni, de la intrare spre iesire. Varianta: mai multe perechi de intrari si iesiri pe 3 biti (log(8)).

Exceptii in PL/SQL

drop table stud;
create table stud (
matricol number(4) primary key,
nume varchar2(30) unique not null,
grupa varchar2(5),
medie number(10,2) check (medie>1 AND medie<=10),
bursa number(3)
);

insert into stud values (1, 'elena', '333CA', 8.7, 0);
insert into stud values (2, 'geanina', '331CA', 5.7, 0);
insert into stud values (3, 'simona', '332CA', 8.2, 0);
insert into stud values (4, 'cornel', '335CA', 9.5, 0);
insert into stud values (5, 'mihai', '334CA', 10, 0);


----------------------------------------------------------
Exceptie cand numele inserat nu este unic:
----------------------------------------------------------

set serveroutput on;

declare
smat number(4);
snume varchar2(30);
sgrupa varchar2(5);
smedie number(10,2);
sbursa number(3);
begin
smat := &matricol;
snume := &nume;
sgrupa := &grupa;
smedie := &medie;
sbursa := &bursa;

insert into stud values (smat, snume, sgrupa, smedie, sbursa);
dbms_output.put_line('inserat cu succes');
exception
when DUP_VAL_ON_INDEX then
dbms_output.put_line(' Nu s-a putut insera: numele nu este unic');
end;
/


-------------------------------------------------------
Exceptie cand bursa nenula pt student cu media<6
-------------------------------------------------------

set serveroutput on;

declare
smat number(4);
snume varchar2(30);
sgrupa varchar2(5);
smedie number(10,2);
sbursa number(3);
bursa_not_allowed exception;
begin
smat := &matricol;
snume := &nume;
sgrupa := &grupa;
smedie := &medie;
sbursa := &bursa;

if smedie<6 AND sbursa>0 then
raise bursa_not_allowed;
end if;
insert into stud values (smat, snume, sgrupa, smedie, sbursa);
dbms_output.put_line('inserat cu succes');

exception
when bursa_not_allowed then
dbms_output.put_line(' Nu s-a putut insera: bursa nenula pt student cu media sub 6');
end;
/


---------------------------------------------------------------
Idem primul exemplu - dar altfel
---------------------------------------------------------------

set serveroutput on;

declare
smat number(4);
snume varchar2(30);
sgrupa varchar2(5);
smedie number(10,2);
sbursa number(3);
default_name varchar2(30);
null_exc exception;
pragma exception_init (null_exc, -1400);
begin
smat := 17;
snume := null;
sgrupa := '321cc';
smedie := 8;
sbursa := 0;
default_name := 'default4';

insert into stud values (smat, snume, sgrupa, smedie, sbursa);
dbms_output.put_line('inserat cu succes');

exception
when null_exc then
dbms_output.put_line('Eroare: numele trebuie sa fie nenul!');
insert into stud values (smat, default_name, sgrupa, smedie, sbursa);
dbms_output.put_line('Am inserat: ' || smat || ' ' || default_name || ' ' || sgrupa || ' ' || smedie || ' ' || sbursa);
end;
/