void readArray( const FINT& unit,
		  const FINT& pos,
		  const FINT& N,
		  T* values,
		  const FINT& threadnum){
    getfilep(unit)->get(pos, N, values, threadnum);
  };
  void writeArray( const FINT& unit,
		   const FINT& pos,
		   const FINT& N,
		   const T* values,
		   const FINT& threadnum){
  getfilep(unit)->set(pos, N, values, threadnum);
  };
  void atomicaddArray( const FINT& unit,
		   const FINT& pos,
		   const FINT& N,
		   const T* values,
		   const FINT& threadnum){
    getfilep(unit)->atomic_add(pos, N, values, threadnum);
  };  
JNIEXPORT void JNICALL 
Java_xxl_core_io_raw_NativeRawAccess_close (JNIEnv *env, jobject obj){
	FILE *jfilep = (FILE*) getfilep(env, obj);
	if (fclose(jfilep)!=0) {
		reportError(env,obj,"Close failed");
		return;
	}
	setfilep(env, obj, 0);
}
JNIEXPORT void JNICALL
Java_xxl_core_io_raw_NativeRawAccess_read (JNIEnv *env, jobject obj, jbyteArray jblock, jlong sector) {
	FILE *jfilep = (FILE*) getfilep(env, obj);		// Get the device int
	jlong fpos;						// The position to read on the device
	jint sectorSize = getsectorSize(env, obj);
	jlong len = (*env)->GetArrayLength(env, jblock); 
	jbyte *block = (*env)->GetByteArrayElements(env, jblock, 0); 
#ifdef SEQ_OPT	
	jlong lastSector = getlastSector(env, obj);
#endif

	DEBUG_OUTPUT("read: sector==%d", (long) sector);
	
	if (jfilep==0) {
		reportError(env,obj,"file not open");
               	return;
	}

	// Is it exactly one block
	if (len!=sectorSize) {
		reportError(env,obj,"byte array does not have sector size");
               	return;
	}

#ifdef SEQ_OPT	
	if (sector != lastSector+1) {
		// non sequential access!
#endif
		fpos = (jlong) sector * sectorSize;
		if (fseek(jfilep,fpos,SEEK_SET)==-1) {
			reportError(env,obj,"filepointer could not be set");
        	       	return;
        	}
#ifdef SEQ_OPT	
	}
#endif

	DEBUG_OUTPUT("read the block",0);
	// Read the block
	if (fread(block, 1, sectorSize, jfilep)!=sectorSize) {
		reportError(env,obj,"read failed");
               	return;
	}
	
	// Convert the c block array to a java byte array
	(*env)->SetByteArrayRegion(env, jblock, 0, sectorSize, block);
#ifdef SEQ_OPT	
	setlastSector(env, obj, sector);
#endif
	(*env)->ReleaseByteArrayElements(env, jblock, block, 0);
}
JNIEXPORT void JNICALL 
Java_xxl_core_io_raw_NativeRawAccess_write (JNIEnv *env, jobject obj, jbyteArray jblock, jlong sector) {
	FILE *jfilep = (FILE*) getfilep(env, obj); 			// Device int
	jlong len = (*env)->GetArrayLength(env, jblock); 		// length of delivered java byte array
	jint sectorSize = getsectorSize(env, obj);
	jbyte *block = (*env)->GetByteArrayElements(env, jblock, 0); 	// Convert it to a c array our sectorblock
	jlong fpos; 							// Position for writing
	
	DEBUG_OUTPUT ("write: sector=%d", (long) sector);

	if (len!=sectorSize) {
		reportError(env,obj,"byte array does not hava sector size");
               	return;
	}
	
	if ((sector<0) || (sector >= getsectorSize(env, obj))) {
		reportError(env,obj,"filepointer outside area");
               	return;
	}

	// Position for writing
	fpos = (jlong) sector * sectorSize;
 
	// Set position
	if (fseek(jfilep,fpos,SEEK_SET)==-1) {
		reportError(env,obj,"filepointer could not be set");
		return;
	}

	// Write the block down to the device
	if (fwrite(block, 1, sectorSize, jfilep)!=sectorSize) {
		reportError(env,obj,"error writing block");
               	return;
	}
	
	if (fflush(jfilep)!=0) {
		reportError(env,obj,"error flushing buffers");
               	return;
	}

	(*env)->ReleaseByteArrayElements(env, jblock, block, 0);
}
  void readBlock( const FINT& unit,
		  const FINT& blockid,
		  T* values,
		  const FINT& threadnum){
    getfilep(unit)->getchunk(blockid, values, threadnum);
  };
  T readElement( const FINT& unit,
		 const FINT& pos,
		 const FINT& threadnum){
    return getfilep(unit)->get(pos, threadnum);}
  void atomicaddElement( const FINT& unit,
			 const FINT& pos,
			 const T& value,
			 const FINT& threadnum){
    getfilep(unit)->atomic_add(pos, value, threadnum);
  };
  void writeBlock( const FINT& unit,
		   const FINT& blockid,
		   const T* values,
		   const FINT& threadnum){
    getfilep(unit)->setchunk(blockid, values, threadnum);
  };
  void writeElement( const FINT& unit,
		     const FINT& pos,
		     const T& value,
		     const FINT& threadnum){
    getfilep(unit)->set(pos, value, threadnum);
  };
JNIEXPORT void JNICALL 
Java_xxl_core_io_raw_NativeRawAccess_open(JNIEnv *env, jobject obj, jstring jfilename) {
	FILE *jfilep; 			// int of the file/device
	jlong sectors;
	fpos_t length;
	// BOOL isDevice=FALSE;
	const jbyte *filename;		// Java needs UTF-coded strings, c needs ASCII
	jint sectorSize;
	
	DEBUG_OUTPUT("Enter open",0);
	init(env, obj);
	
	// do not call get methods before init!
	jfilep = (FILE*) getfilep(env, obj);
	sectorSize = getsectorSize(env, obj);
	// Converts utf to ASCII
	filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
	// got it?
	
	if (filename==NULL) {
		reportError(env,obj,"Filename NULL");
		return;
	}
	
	// Already a device open?
	if (jfilep!=0) {
		reportError(env,obj,"File already open");
		return;
	}

  	DEBUG_OUTPUT("Filename: %s",filename);
  	
  	//if ( (filename[0]=='\\') && (filename[1]=='\\') && (filename[2]=='.') && (filename[3]=='\\') )
  	//	isDevice=TRUE;
  		
	jfilep = fopen(filename,"rwbc");

	// Open failed?
	if (jfilep==NULL) {
		reportError(env,obj,"Open failed - file not found");
		return;
	}

	// Set the int inside the java object
	setfilep(env, obj, (jlong) jfilep);
  	DEBUG_OUTPUT("Filepointer: %d",(long) jfilep);

	setbuf(jfilep, NULL);

	if (fseek(jfilep,0,SEEK_END)!=0) {
		reportError(env,obj,"seek failed");
		return;
	}

	fgetpos(jfilep,&length);
	if (length==-1) {
		reportError(env,obj,"Size returned 0");
		return;
	}
	else  
		sectors = length/sectorSize;
		
  	DEBUG_OUTPUT("Sektoren: %d\n", (long) sectors);
	setsectors(env, obj, (jlong) sectors);
}