Tuesday, 31 July 2012

fork() vs vfork().

For more info visitvfork() is same as fork(), it also creates a new process when it is called. The only difference is that, it doesn't copy the address space of parent into the address space of child. The main intention of using vfork() is that, child will run a new program using exec as soon as it is created, and so, shall not need a reference to the parent's address space.

After the child process is created, it runs on parent's address space until exec or exit is called. This means, both child and parent share the same address space until exec or exit is called.

vfork() also guarantees that after forking, child will be the first one to run until exec or exit is called. While the child process is running, before calling exec or exit, parent process will not run. Parent process will resume only when exec or exit is called by the child process.

Below given is a simple example, which will help you to understand the difference between them.

Compile and execute the following program

 
#include<stdio.h>
#include<stdlib.h>
int main()
{
int pid,var=1;
if((pid=vfork())==0)
{
// Child process starts
var=var+1;
exit(0);
// Child process ends
}
// Parent process continues
printf("value of var %d",var);
return 0;
}


Note the value of var. The output will be

value of var 2.

As we can see, the value of var in parent's address space has been changed by the child process. This means, no other address space was created for child, unless exec was called.

Now run the same program using fork() instead of vfork(), and the output will be

value of var 1.

This is because, we are changing var in child's address space, so value in parent's address space will not change.

 

Monday, 16 July 2012

Records in PL/SQL.

For more info visit

A record, as the name signifies, is a collection of more than one fields in a variable. For those of you who are familiar with language "C", you can compare a record to a structure in "C". The fields of a record can be of sql  or pl/sql type.

There are two ways in which a record can be declared.

1) Using Anchor Declarations(Table Based or Cursor Based Records).

ex:   employee_details employee%ROWTYPE;

Here employee is a table . Suppose, employee table has structure as shown below.

 EMP_ID                                             NOT NULL                 NUMBER
 EMP_NAME                                    NOT NULL                 VARCHAR2(10)

 We can collect the values corresponding to some row of a table in the record as

SELECT * into employee_details FROM employee WHERE emp_id  = 1;

and after that, we can access or manipulate the fields in the record using ".".

employee_details.emp_name

In the same way, we can also declare a record of Cursor type

CURSOR employee_cursor is SELECT * into employee_details FROM employee WHERE emp_id  = 1;

emp_cur employee_cursor%ROWTYPE;

We can directly fetch values from cursor into our record as

OPEN employee_cursor;

FETCH employee_cursor INTO emp_cur;

2) Programmer Defined Records:

In a programmer defined records, we can decide the field of our records. It doesn't have to be dependent on any table or cursor for its structure. These type of records are declared as

TYPE emp_rec IS RECORD

( name employee.emp_name%TYPE,

age NUMBER(3),

salary NUMBER(10) := 0

);

employee_record emp_rec;

In this type of record, we are free to define our own fields with different datatypes. We can always specify [NOT NULL]:=[DEFAULT] with the fields of a record. These types of records are useful when we want to collect data from different tables or when our record has nothing to do with tables or cursors.

We can manipulate the fields of these type of records in a number of ways, for example

employee_record.name := 'John';

select name into employee_record.name from employee where emp_id = 1;

 Note:

1) Two records cannot be compared as rec1=rec2, even if they are of same record type. Comparision of two records can only be done on field basis.

2) Values of a record can be assigned to other record if they are of same record type.

rec1 := rec2;

3) Records can be passed as parameters or can be returned from a function.

4) IS NULL cannot be used to check if all the fields of a record are NULL.

5) NULL can be assigned to a record as

rec1 := NULL;

6) We can insert the whole record into a table(without using individual fields), only if the record is declared using anchored declaration.

emp_rec employee%ROWTYPE;

insert into employee values emp_rec;

Sunday, 8 July 2012

Difference between dup() and dup2().

For more info visitdup() and dup2() are system calls which are used to duplicate file descriptors. Each process has a file descriptor table which contains the pointers to the file tables, process is using.

File descriptors are generally indexes of that table. The real information, i.e. the File pointer, is stored corresponding to these indexes. File pointer points to the file table which contains various attributes of files, such as current offset of file, file status flag, v-node information etc. Whenever a process forks, i.e creates a new child process, all the information in this table is copied to the child process's memory space.

While the information is copied from parent to child process, file pointer information from file descriptor table is also copied, so both the file pointers in both the memory spaces(child as well as Parent) point to the same File table. All the attributes in the File table( for the copied file pointers) are common for both, child as well as Parent.

This was the brief description about how the files descriptors work in the process. For detail information about file descriptors visit.

Now, as told earlier, dup() and dup2() are system calls which are used to duplicate file descriptors. By duplicating file descriptors we mean, the pointer information is copied from one location of the descriptor table to other location, no new file table is made for this process, only the file table is pointed by one more location in the descriptor table.

dup() : dup(int filedes) takes a file descriptor as its argument and duplicates the next lowest available file descriptor with the same file table pointer. It returns the new file descriptor value.

Suppose in a process, we want to duplicate the output file descriptor (1). Call

dup(1)

which will return the next lowest available file descriptor. If the process has

0 as the input descriptor

1 as output descriptor

2 as error output descriptor.

then calling the dup() will return 3 as the next available file descriptor, which will point to the terminal(same as 1).

dup2() : Using dup(), we are never sure about the value which will be returned. It will automatically return the next lowest available file descriptor. In some cases, we may need to duplicate a file descriptor as another file descriptor, we use dup2().

dup2(int filedes1, int filedes2) takes two file descriptors as its arguments. Let's suppose, we want to duplicate file descriptor 5 with file descriptor 1, i.e we want the file descriptor 5 to point at the same file table as file descriptor 1.

We will call dup2(1,5). It first checks, if file descriptor 5 is already open. If it's open, it closes the file descriptor 5 and opens it again, with the pointer pointing to the same file table, in the same way as 1.

If file descriptor 5 was already pointing to that table, it returns -1.

One more thing, we could have implemented the same functionality as below.

close(filedes2)

dup(filedes1)

But we don't do it like this. Why?

If we see, the above two operations are not atomic, i.e. we have a slight open time window between call to close and call to dup, so there is a possibility of some signal handler function(in case we receive a signal between these two calls) to alter the pattern of file descriptors. 

Generally, we use these duplicate system calls in case of Inter Process Communication, where we make pipes for the communication between two processes.

Monday, 2 July 2012

Oracle WITH Clause.

For more info visit

WITH clause is also known as Subquery factoring clause. It is used to simplify the structure of complex queries, and in some cases, optimize the queries.

With clause works in the same way as a Temporary table or an inline view, but the main difference between With clause and, an inline view or a Temporary table is that, a query written using With clause is less complex and easier to understand.

When we use a With clause, it depends on the optimizer whether it will make temporary table or an inline view, corresponding to the subquery in the With clause. This also depends on the subqueries used in With clause, if the queries are too complex then the optimizer may create Temporary tables ,else an inline view is sufficient.

We can also pass Optimizer hints in the subqueries written in with clause, to request the optimizer for an inline view or a Temporary table.

Select /*+ MATERIALIZE */ .... For Temporary table

Select /*+ INLINE */ ..... For Inline view

Now let's see an example, with and without With clause.

Suppose I want to find out the names of the employees having salary greater than the average salary of the department in which they work.

I can write this query in 3 ways.

1) Using Corelated Subqueries.

select ed1.name from employee_details ed1
where salary>(select avg(salary) from
employee_details ed2 where
ed1.department=ed2.department)

Writing corelated subquery is fine when data in the tables is less, but when there is a large amount of data in tables then this approach may not be suitable. For each employee in the table, the subquery will execute. So, we discard this approach in case of huge amount of data in tables.

2) The second approach is to create Inline view.

select ed1.name from employee_details ed1,
(Select avg(salary) sal,department
from employee_details group by
department) ed2 where ed2.department=ed1.department
and ed1.salary > ed2.sal

Here, an inline view is created, which is more efficient in case of huge amount of data. The query given above contains only one inline view, but what about the queries containing many inline views. It will become very complex to understand.

3) Using With Clause.

There is not much difference between aWith clause and an inline view, except the way of writing queries becomes more understandable.

Now, let's see the same query using a With Clause.

With ed2 as(Select avg(salary) sal,department
from employee_details group by
department)
select ed1.name from employee_details ed1,
ed2
where ed1.department=ed2.department and
ed1.salary>ed2.sal

The queries using With clause starts with With instead of Select, which may seem wierd at first, but as you start using With Clause, it will become inseparable part of  writing simple and understandable queries.

With clause may come handy in a lot of other situations(demanding subqueries), the only limit is how efficiently we can reduce the complexity of our queries using With Clause.