/* Speedtest V1.0
	Autor: Andreas Krämer
	KICKSTART 1989
	Das Programm Speedtest V1.0 ist Public Domain,
	Änderungen im Source-Code müssen angegeben werden!!!

	Aztec C V3.4, V3.6
	cc speedtest.c
	ln speedtest.o -lc
*/

#include "exec/types.h"
#include "libraries/dosextens.h"
#include "libraries/dos.h"
#include "exec/memory.h"
#include "functions.h"
#include "stdio.h"

/* Anzahl der zu erzeugenden Dateien */

#define Anzahl_Dateien 10L

/* Allgemeine Variablen und Strukturen */

struct Dat
{
  char Datname[25];
};

extern struct DOSLibrary *DOSBase;
static struct FileLock *FileLock, *Lock();
static struct FileInfoBlock InfoBlock;
static struct FileHandle *datei, *datei2, *datei3, *Open();
static long int FileSize, Position, count=0L;
static char *FILEPUFFER;
static char Testdatei[30];
static char *Name[];
static char *Devname[Anzahl_Dateien];
static char Testname[30];
LONG Del_ERR;
int start, end, k;
long int exam, seekc;
static struct Dat Datanzahl[Anzahl_Dateien];

/* Die verschiedenen Programm-Module */
/* sync_ticks() und cur_ticks() sind für die Zeitausgabe */

sync_ticks()
  {
	struct TIME
	{
	  long days,minutes,ticks;
	} t;
	long ticks;

	DateStamp(&t);
	ticks = t.ticks;
	do
	{
	  DateStamp(&t);
	} while (t.ticks == ticks);
	return(3000*t.minutes + t.ticks);
}

cur_ticks()
{
	struct TIME
	{
		long days,minutes,ticks;
	} t;
	DateStamp(&t);
	return(3000*t.minutes + t.ticks);
}

/* Erstellt die Dateinamen von Anzahl_Dateien (10) */

ErstelleDateinamen()
{
  for(k=0;k<Anzahl_Dateien;k++)
  {
	 itoa(k,Name[k]);
	 strcpy(Testname,Testdatei);
	 strcat(Testname,Name[k]);
	 strcpy(Datanzahl[k].Datname,Testname);
  }
}

/* Erstes Testmodul, die Datei wird gespeichert in der
	angegebenen Größe */

Speichern()
{
	printf("\nSPEICHERN:       ");
	if(!(datei2 = Open(Testdatei,MODE_NEWFILE)))
	{
		 if(FILEPUFFER)FreeMem(FILEPUFFER,FileSize);
		 printf("\n Fehler Speichern");
		 exit(FALSE);
	 }
	 start = sync_ticks();
	 Write(datei2,FILEPUFFER,FileSize);
	 end = cur_ticks();
	 Close(datei2);
	 /* Ergebnisausgabe */
	 printf("%d.%02d Sekunden", (end-start)/50, ((end-start)%50)*2);
	 printf("   %ld Bytes/Sekunde",(FileSize*100L)/(((((end-start)/50)*100L)+ (((end-start)%50)*2))+1L));
}

/* Lademodul; läd die zuvor geschriebene Datei */

Laden()
{
	printf("\nLADEN:           ");
	if(!(datei = Open(Testdatei,MODE_OLDFILE)))
	  {
		if(FILEPUFFER)FreeMem(FILEPUFFER,FileSize);
		printf("\n Fehler Laden");
		exit(FALSE);
	  }
	start = sync_ticks();
	Read(datei,FILEPUFFER,FileSize);
	end = cur_ticks();
	Close(datei);
	printf("%d.%02d Sekunden", (end-start)/50, ((end-start)%50)*2);
	printf("   %ld Bytes/Sekunde",(FileSize*100L)/(((((end-start)/50)*100L)+ (((end-start)%50)*2))+1L));
}

/* Der Seek-Test in 256 Byte-Schritten
	Zeigerposition in der Datei verstellen */

Se_Test()
{
	printf("\nSEEK-TEST:                  ");
	if(!(datei2 = Open(Testdatei,MODE_OLDFILE)))
	  {
		printf("\n Fehler Seek\n");
		exit(FALSE);
	  }
	start = sync_ticks();
	for(seekc=0L;seekc<FileSize;seekc+=256L)
	{
		count++;
		if(!( Read(datei2,FILEPUFFER,1L)))
		{
			printf("Fehler SEEK bei READ \n");
			Close(datei2);
			if(FILEPUFFER)FreeMem((char*)FILEPUFFER,(long)FileSize);
			exit(FALSE);
		}
		if(!(Position = Seek(datei2,seekc,OFFSET_BEGINNING)))
		{
			printf("Fehler SEEK\n");
			Close(datei2);
			if(FILEPUFFER)FreeMem((char*)FILEPUFFER,FileSize);
			exit(FALSE);
		}
	}
	end = cur_ticks();
	Close(datei2);
	printf("       %ld Seeks/Sekunde",(count*100L)/(((((end-start)/50)*100L)+ (((end-start)%50)*2))+1L));
}

/* Examine-Test; mit Lock() und UnLock()
	Dateiinformationen besorgen */

Ex_Test()
{
  printf("\nEXAMINE:                ");
  count = 0L;
  start = sync_ticks();

  for(exam=1L;exam<100L;exam++)
  {
	 count++;
	 if(!(FileLock = Lock(Testdatei,SHARED_LOCK)))
	 {
		printf("Kein Lock\n");
		exit(FALSE);
	 }
	 if(!(Examine(FileLock,&InfoBlock)))
	 {
		 printf("Examine Fehler\n");
		 UnLock(FileLock);
		 exit(FALSE);
	 }
	 UnLock(FileLock);
	}
	end = cur_ticks();
	printf("           %ld Examine/Sekunde",(count*100L)/(((((end-start)/50)*100L)+ (((end-start)%50)*2))+1L));
}

/* Löscht geschriebene Datei */

Datei_Loeschen()
{
  Del_ERR = DeleteFile(Testdatei);
  if(Del_ERR=FALSE)
  {
	 printf("Testdatei nicht gelöscht !!!\n");
	 exit(FALSE);
  }
  if(FILEPUFFER)FreeMem((char*)FILEPUFFER,(long)FileSize);
  Delay(20L);
}

/* Create&Close-Test; erzeugt die in Anzahl_Dateien definierte
	Anzahl von Files */

CrCl_Test()
{
	printf("\nCREATE&CLOSE:            ");
	start = sync_ticks();
	for(k=0;k<Anzahl_Dateien;k++)
	{
	 if(!(datei3 = Open(Datanzahl[k].Datname,MODE_NEWFILE))) exit(FALSE);
	 Close(datei3);
	}
	end = cur_ticks();
	printf("           %ld Create&Close/Sekunde",(Anzahl_Dateien*100L)/(((((end-start)/50)*100L)+ (((end-start)%50)*2))+1L));
}

/* Löscht die mit CrCl_Test() erzeugten Dateien */

Loeschen()
{
	printf("\nDELETE:                  ");
	start = sync_ticks();
	for(k=0;k<Anzahl_Dateien;k++)
	{
	 Del_ERR = DeleteFile(Datanzahl[k].Datname);
	 if(Del_ERR=FALSE)
	 {
		printf("Testdateien nicht gelöscht !!!\n");
	 }
	}
	end = cur_ticks();
	printf("           %ld Delete/Sekunde",(Anzahl_Dateien*100L)/(((((end-start)/50)*100L)+(((end-start)%50)*2))+1L));
}

/* Wandelt Integer in String */

itoa(n,s)
register int n;
register char *s;
{
	register int i = 0;
	register int vorzeichen = 0;

	if(n < 0)
	{
		vorzeichen = TRUE;
		n = -n;
	}
	do  s[i++] = n%10 + '0';
	while(n /= 10);
	if(vorzeichen) s[i++] = '-';
	s[i] = '\0';
	reverse(s);
 }

/* dreht String */

 reverse(s)
 register char *s;
 {
	register int c, i, j;
	for (i = 0,j = strlen(s)-1; i<j;i++,j--)
	{
		c	  = s[i];
		s[i] = s[j];
		s[j] = c;
	}
}

/*  Das Hauptprogramm */

main(argc,argv)
int argc;
char *argv[];
{

/* Syntaxüberprüfung, es müssen immer zwei Argumente übergeben werden,
	ansonsten ABBRUCH */

if(*argv[1] == '?' || argc < 3)
 {
	  printf("Speedtest <Device> <Dateigröße in KByte>\n");
	  exit(FALSE);
 }
 FileSize = atol(argv[2]); /* String-Argument in LONG-Wert umwandeln */
 FileSize *= 1024L;			/* Mache KB daraus */
 strcat(argv[1],"Testdatei\0"); /* Name der Datei erzeugen */
 strcpy(Testdatei,argv[1]);

 /* Dateispeicher reservieren */

 if(!(FILEPUFFER=(char *)AllocMem(FileSize,MEMF_CLEAR | MEMF_PUBLIC)))
  {
	 printf("Speicherfehler\n");
	 exit(FALSE);
  }
 printf("\nSpeedtest V1.0\n");
 printf("Performance-Test von Speichermedien\n");
 printf("Autor: Andreas Krämer\n");
 printf("\nLaden und Speichern von %ld KByte\n",FileSize/1024L);

/* Aufruf der verschiedenen Programm-Module */

 ErstelleDateinamen();
 Speichern();
 Laden();
 Se_Test();
 Ex_Test();
 Datei_Loeschen();
 CrCl_Test();
 Loeschen();
 printf("\n");
 exit(TRUE);
} /* LISTING ENDE */
