/*
Ordena um arquivo de NUMINT inteiros aleatórios em formato binário usando
mapeamento em memório (mmap) para acesso aos dados do arquivo.

Antes de executar, criar um arquivo com NUMINT inteiros aleatórios em formato
binário (4 bytes por inteiro). Pode-se fazer isso por exemplo com:

	dd if=/dev/urandom of=randomint.dat bs=SIZE count=1

com SIZE sendo 4 * NUMINT.

Carlos Maziero, DINF/UFPR 2020
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

// número de valores int no arquivo de dados
#define NUMINT 10000000

int *vet ;
int num ;
FILE *datafile;

// compara dois inteiros (para a função qsort)
int compara (const void *p1, const void *p2)
{
  int *i1 = (int*) p1 ;
  int *i2 = (int*) p2 ;

  if (*i1 < *i2) return (-1) ;
  if (*i1 > *i2) return ( 1) ;
  return (0) ;
}

int main (int argc, char *argv[], char *envp[])
{
  // abre o arquivo de dados
  if (argc < 2)
  {
     printf ("Error: should inform a file name\n") ;
     exit (1) ;
  }
  datafile = fopen (argv[1], "r+") ;
  if ( !datafile)
  {
    perror ("Error fopen") ;
    exit (1) ;
  }

  // mapeia o arquivo de dados na memória
  vet = mmap (NULL,			// o núcleo define local desta área
              NUMINT * sizeof(int),	// o tamanho da área mapeada
              PROT_READ|PROT_WRITE,	// pode-se ler e escrever nela
              MAP_SHARED,		// escritas serão enviadas ao arquivo
              fileno (datafile),	// descritor UNIX do arquivo
              0);			// começa no início do arquivo

  // ordena o vetor de dados (quicksort)
  qsort (vet, NUMINT, sizeof (int), compara) ;

  // desmapeia arquivo de dados da memória
  munmap (vet, NUMINT * sizeof(int)) ;
  fclose (datafile) ;

  exit (0) ;
}

