Ejemplo n.º 1
0
	/// <summary>
	/// wait for the specficed ms until keypressed
	/// </summary>
	/// <param name="ms">The ms to wait.</param>
	/// <returns>The key pressed(ASC-II not guaranteed).</returns>
	int waitkey(double ms)
	{
		int key = -1;
		double start = get_real_time();
		double end = start + ms / 1000;

#if defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
		set_conio_terminal_mode();
#endif

		if (ms <= 0)
		{
			// disable timer if ms <= 0
			end = DBL_MAX;
		}

		while (key == -1)
		{
			key = kb_hit();
			//printf("%d", (int)get_elapsed_time_ms(start));
			if (get_real_time() >= end)
			{
				break;
			}
		}
		//std::cin.get();
#if defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
		reset_terminal_mode();
#endif
		return key;
	}
Ejemplo n.º 2
0
double get_time_resolution()
{
    double T0=get_real_time();
    for (int k=0; k<1000000; k++)
    {
        double t1= get_real_time()-T0;
        double t2 = get_real_time()-T0;
        
        if ( t2-t1 != 0)
            return (t2-t1);
    }
}
Ejemplo n.º 3
0
/**
 * \brief Initializes the basic low-level system.
 *
 * Initializes the audio system, the video system,
 * the data file system, etc.
 *
 * \param args Command-line arguments.
 */
void System::initialize(const Arguments& args) {

  // initialize SDL
  SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  initial_time = get_real_time();
  ticks = 0;

  // files
  FileTools::initialize(args);

  // audio
  Sound::initialize(args);

  // input
  InputEvent::initialize();

  // random number generator
  Random::initialize();

  // video
  Video::initialize(args);
  Color::initialize();
  FontResource::initialize();
  Sprite::initialize();
}
Ejemplo n.º 4
0
PackageLinksDirectory::PackageLinksDirectory()
	:
	Directory(0),
	fListener(NULL)
		// the ID needs to be assigned later, when added to a volume
{
	get_real_time(fModifiedTime);
}
Ejemplo n.º 5
0
void
client_main_loop (void)
{
    int quit = 0;
    int engine_updated = 0;

    /* Set up the game */
    reset_start_time ();

    update_avail_modules (0);

    screen_full_refresh ();

    if (no_init_help == 0) {
	block_help_exit = 1;
	help_flag = 1;
	if (make_dir_ok_flag) {
	    activate_help ("ask-dir.hlp");
	    make_dir_ok_flag = 0;
	} else {
	    activate_help ("opening.hlp");
	}
    }

    /* Set speed */
#if defined (CS_PROFILE) || defined (START_FAST_SPEED)
    select_fast ();
#else
    select_medium ();
#endif
    /* Main Loop */
    do {
	int key;

	/* Get timestamp for this iteration */
	get_real_time();

	/* Process events */
#if defined (LC_X11)
	call_event ();
	key = x_key_value;
	x_key_value = 0;
#elif defined (WIN32)
	call_event ();
	key = GetKeystroke ();
#else
	mouse_update ();
	key = vga_getkey ();
#endif
	/* nothing happened if key == 0 XXX: right? */
	/* GCS: I'm not sure */
	if (key != 0) {
            process_keystrokes (key);
	}
	/* Simulate the timestep */
	quit = execute_timestep ();
    } while (quit == 0);
}
void doLincityStep()
{
  /* Get timestamp for this iteration */
  get_real_time();
  
  execute_timestep ();
  
  //  return true;
}
Ejemplo n.º 7
0
int main()
{
    std_setup();
    
    int n = 256;
    double x0 = ml_pi;
    
    double tf = 1.0;
    double dt = 0.1;
    
    grid2D<double,double,double > grid( n,-x0,x0, n,-x0,x0 ),u,v,C2,damp;
    grid = 0.0;
    
    u = grid;
    v = grid;
    C2 = grid;
    
    C2 = 1.0;
    u = u_0_func();
    
    sprintf(fname,"/workspace/output/acoustic_propagate_2d/out_dat/C2.dat", n);
    writeFile(C2,fname);
    
    linear_propagator P;
    P.init( grid, 1, C2 );
    
    double t = 0.0;
    
    while (t <= tf)
    {
        output(t,u,v);
        
        double t1 = get_real_time();
        
        P( dt, u,v,u,v );
        
        double t2 = get_real_time();        
        cout << t << "\t" << t2-t1 << endl;
        
        t += dt;
    }
       
    output(t,u,v);
}
Ejemplo n.º 8
0
	void CRefresher::deal(workbench_t &bench)
	{
		char * tmp;
		tmp = create_cp(bench);
		string new_cp(tmp);
		
		bool changed = false;
		int old_timeout = bench.timeout;
#ifndef _TEST
		//if there is no url=bench.url in our file, we write delete log too
		if (bench.reply.status.code == 404)	
		{
			time_t timep;
			time(&timep);
//			fprintf(deletelog,"delete url %s %s\n",
//				bench.url->str().c_str(), ctime(&timep));
		return;
	}
#endif
	if (bench.timeout == 0)
	{
		changed = true;	//first time crawled
		time_t timep;
		time(&timep);
//		fprintf(newlog,"new url %s %s\n",
//			bench.url->str().c_str(), ctime(&timep));
	}
	else{
		if (new_cp != bench.checkpoint)
		{				//changed
			changed = true;
	
			time_t timep;
			time(&timep);
//			fprintf(changelog,"change url %s %s\n",
//				bench.url->str().c_str(), ctime(&timep));
		}
	}
	
	bench.changed = changed;	
	bench.timeout = rconfig.calculate(bench.url.str().c_str(),old_timeout,changed,bench.depth);
	
	CTime_struct real_time = get_real_time(bench.timeout);
#ifdef _TEST
	cout << "new real_time = " << real_time.time_to_string() << endl;
#endif
	
#ifndef _TEST
	bench.checkpoint = new_cp;
#endif

	save_to_file(bench,real_time);
}
Ejemplo n.º 9
0
static void test_realtime()
{
    return; 
    real_time_t rt;
    get_real_time(&rt);
	
    s32 y = 550;
    draw_hex8(rt.rt_year,	650, y + 20*0, color);
    draw_hex8(rt.rt_month,	650, y + 20*1, color);
    draw_hex8(rt.rt_day,	650, y + 20*2, color);
    draw_hex8(rt.rt_hour,	650, y + 20*3, color);
    draw_hex8(rt.rt_minute,	650, y + 20*4, color);
    draw_hex8(rt.rt_second,	650, y + 20*5, color);
}
Ejemplo n.º 10
0
double Real_timer::compute_precision() const {
    // Computes timer precision in seconds dynamically. Note that
    // the timer system call is probably non-trivial and will show
    // up in this time here (probably for one call). But that is just
    // fine that the call to the timer itself if reported as noise 
    // in the precision.
    double min_res = DBL_MAX;
    for ( int i = 0; i < 5; ++i) {
        double current = get_real_time();
        if ( m_failed)
            return -1.0;
        double next    = get_real_time();
        while ( current >= next) { // wait until timer increases
            next = get_real_time();
            if ( m_failed)
                return -1.0;
        }
        // Get the minimum timing difference of all runs.
        if ( min_res > next - current)
            min_res = next - current;
    }
    return min_res;
}
Ejemplo n.º 11
0
long
get_msec_real_time (void)
{
#if 0
  struct timezone tz;
  struct timeval time;
  gettimeofday (&time, &tz);
  return ((time.tv_sec * 1000) + (time.tv_usec / 1000));
#endif

  get_real_time (&time_now);
  time_now_msec = time_now.to_sec * 1000 + time_now.to_usec / 1000;
  return approx_msec_real_time ();
}
Ejemplo n.º 12
0
void *threadFunc(void *args)
{
    double T0 = *(double*)args;
    int tres = *(int*)((char*)args+8);    
    
    for (int k=0; k<100; k++)
    {
        cout << "t\t" << (get_real_time()-T0)*tres << endl;
    }
    
    
    
	return NULL;
}
Ejemplo n.º 13
0
int main()
{
    std_setup();
    
    

    double T0;
    int tres=0;
    tres = 1.0/get_time_resolution();
    T0=get_real_time();
    cout << tres << endl;
    
    
    
    
    pthread_t pth;
    
    char args[100];
    *(double*)args =T0;
    *(int*)(args+8)=tres;
    
    
    pthread_create( &pth, NULL, threadFunc, (void*)args );
    
    pthread_join(pth, NULL);
    
    for (int k=0; k<100; k++)
    {
        cout << "m\t" << (get_real_time()-T0)*tres << endl;
    }
    
    
    
	
    
    std_exit();
}
Ejemplo n.º 14
0
int
main (int argc, char *argv[])
{
    char* load_filename;

    /* Initialize some global variables */
    initialize_server ();

    /* Set up the paths to certain files and directories */
    init_path_strings ();

#ifndef CS_PROFILE
#ifdef SEED_RAND
    srand (time (0));
#endif
#endif

    init_types ();
    initialize_tax_rates ();

    reset_start_time ();

    load_filename = parse_server_args (argc, argv);
    if (load_filename && file_exists(load_filename)) {
	printf ("Server is trying to load: %s\n", load_filename);
	load_city (load_filename);
	zoom_originx = main_screen_originx;
	zoom_originy = main_screen_originy;
    } else {
	engine_new_city (&zoom_originx, &zoom_originy, 1);
    }

    printf ("Server starting main loop!\n");
    while (1) {
	sniff_packets ();
	engine_do_time_step ();
	get_real_time ();
	send_periodic_messages ();
	if (total_time % 1000 == 0) {
	    debug_print_stats ();
	}
    }

    return 0;
}
Ejemplo n.º 15
0
long
approx_msec_real_time (void)
{
/*  return (time_now.to_sec * 1000 + time_now.to_usec / 1000); */
  static timeout_t ret;

  if (boot_time.to_sec == 0)
    {
      get_real_time (&boot_time);
      return 0;
    }
  if (time_now.to_usec >= boot_time.to_usec)
    {
      ret.to_sec = time_now.to_sec - boot_time.to_sec;
      ret.to_usec = time_now.to_usec - boot_time.to_usec;
    }
  else
    {
      ret.to_sec = time_now.to_sec - boot_time.to_sec - 1;
      ret.to_usec = time_now.to_usec + 1000000 - boot_time.to_usec;
    }
  return last_approx_msec_real_time = ret.to_sec * 1000 + (ret.to_usec + 500) / 1000;
}
Ejemplo n.º 16
0
int main()
{
    std_setup();
    
    int n = 256;
    double x0 = 10;
    
    double tf = 10.0;
    double dt = 0.05;
    int expansion_order = 7;
    int hdaf_order = 8;
    
    grid2D<double,double,double > grid( n,-10,10.0, n,-10,10.0 ),u,v,C2,damping;
    grid = 0.0;
    
    u = grid;
    v = grid;
    C2 = grid;
    damping = grid;
    
    u = u_0_func();
    C2 = C2_func();
    damping = damping_func();
    
    sprintf(fname,"/workspace/output/acoustic_propagate_2d/out_dat/C2.dat" );
    writeFile(C2,fname);
    
    
    void * pdata = 0;
    method1_init( &pdata, grid.n1, grid.n2, grid.dx1(), grid.dx2(), C2.array, damping.array, 7, hdaf_order, hdaf_order, 0.8, 0.8 );
    
    //acoustic_propagator P;
    //P.init( grid, 7, C2, damping );
    
    double t = 0.0;
    
    cout << "step: " << t << "\t" << L2norm(u) << endl;
    
    n=0;
    double * b_times = new double [ int(tf/dt+5) ];
    
    while (t <= tf)
    {
    
        output(t,u,v);
        
        double t1 = get_real_time();
        
        method1_execute( pdata, dt, u.array,v.array,u.array,v.array );
        //P( dt, u,v,u,v );
        
        double t2 = get_real_time();
        
        b_times[n] = t2-t1;
        double mean = 0;
        for (int j=0; j<n; j++)
            mean += b_times[j]/n;
        cout << mean << endl;
        n++;
        
        
        double mag = L2norm(u);
        cout << "step: " << t << "\t" << t2-t1 << "\t" << mag << endl;
        
        t += dt;
        
        if ( mag > 1E10 ) break;
    }
       
    output(t,u,v);
}
Ejemplo n.º 17
0
void
si_scroll_text (void)
{
  char s[LC_PATH_MAX], line1[100], line2[100], line3[100], c;
  int i, t, l1c = 0, l2c = 0, l3c = 0;
  FILE *inf1, *inf2, *inf3;
#ifdef LC_X11
  XEvent xev;
#endif
  Fgl_enableclipping ();
  sprintf (s, "%s%c%s", opening_path, PATH_SLASH, "text1");
  if ((inf1 = fopen (s, "rb")) == NULL)
    do_error ("Can't open opening/text1");
  for (i = 0; i < 52; i++)
    line1[i] = si_next_char (inf1);
  line1[52] = 0;
  sprintf (s, "%s%c%s", opening_path, PATH_SLASH, "text2");
  if ((inf2 = fopen (s, "rb")) == NULL)
    do_error ("Can't open opening/text2");
  for (i = 0; i < 52; i++)
    line2[i] = si_next_char (inf2);
  line2[52] = 0;
  sprintf (s, "%s%c%s", opening_path, PATH_SLASH, "text3");
  if ((inf3 = fopen (s, "rb")) == NULL)
    do_error ("Can't open opening/text3");
  for (i = 0; i < 52; i++)
    line3[i] = si_next_char (inf3);
  line3[52] = 0;
  do
    {
      get_real_time ();
      t = real_time + SPLASH_SCROLL_DELAY;
#ifdef LC_X11
      if (XPending (display.dpy))

	{
	  XNextEvent (display.dpy, &xev);
	  HandleEvent (&xev);
	}

      c = x_key_value;
#elif defined (WIN32)
      c = GetKeystroke ();
#elif defined LC_SVGA
      c = vga_getkey ();
#endif
      if (l1c >= 8)
	{
	  for (i = 0; i < 51; i++)
	    line1[i] = line1[i + 1];
	  line1[51] = si_next_char (inf1);
	  l1c = 0;
	}
      Fgl_setfont (8, 8, start_font1);
      Fgl_setclippingwindow (120, 30, 520, 40);
      Fgl_setfontcolors (SI_BLACK, SI_RED);
#if defined (LC_X11) || defined (WIN32)
      open_write (120 - l1c, 31, line1);
#else
      Fgl_write (120 - l1c, 31, line1);
#endif
      l1c++;

      if (l2c >= 8)
	{
	  for (i = 0; i < 51; i++)
	    line2[i] = line2[i + 1];
	  line2[51] = si_next_char (inf2);
	  l2c = 0;
	}
      Fgl_setfont (8, 16, start_font2);
      Fgl_setclippingwindow (120, 55, 520, 73);
      Fgl_setfontcolors (SI_BLACK, SI_GREEN);
#if defined (LC_X11) || defined (WIN32)
      open_write (120 - l2c, 57, line2);
#else
      Fgl_write (120 - l2c, 57, line2);
#endif
      l2c += 2;

      if (l3c >= 8)
	{
	  for (i = 0; i < 51; i++)
	    line3[i] = line3[i + 1];
	  line3[51] = si_next_char (inf3);
	  l3c = 0;
	}
      Fgl_setfont (8, 16, start_font3);
      Fgl_setclippingwindow (120, 88, 520, 106);
      Fgl_setfontcolors (SI_BLACK, SI_YELLOW);
#if defined (LC_X11) || defined (WIN32)
      open_write (120 - l3c, 90, line3);
#else
      Fgl_write (120 - l3c, 90, line3);
#endif
      l3c += 2;
#if defined (WIN32)		/* Scroll a little faster for WIN32 */
      if (pix_double)
	{
	  l1c += 10;
	  l2c += 10;
	  l3c += 10;
	}
      else
	{
	  l1c += 2;
	  l2c += 4;
	  l3c += 4;
	}
#endif
      while (real_time < t)
	{
	  lc_usleep (1);
	  get_real_time ();
	}
    }
  while (c == 0);
  fclose (inf1);
  fclose (inf2);
  fclose (inf3);
  Fgl_disableclipping ();
}
Ejemplo n.º 18
0
unsigned long
get_user_time(void)
{
  return get_real_time();
}
Ejemplo n.º 19
0
	//////////////////////////////// Timer class ////////////////////////////////////
	/// <summary>
	/// Updates the current timestamp.
	/// </summary>
	void Timer::update()
	{
		timestamp = get_real_time();
	}
Ejemplo n.º 20
0
	/// <summary>
	/// Get the time elapsed in second since last update.
	/// </summary>
	/// <returns>The time elapsed in second</returns>
	double Timer::get_elapsed_time_s()
	{
		return get_real_time() - timestamp;
	}
Ejemplo n.º 21
0
	/// <summary>
	/// Get the time elapsed in us since last update.
	/// </summary>
	/// <returns>The time elapsed in us</returns>
	double Timer::get_elapsed_time_us()
	{
		return (get_real_time() - timestamp) * 1000000.0;
	}
Ejemplo n.º 22
0
/** Write to an AFS file
 * \par Description:
 * Write from the given buffer into the given file starting at the given offset for
 * the given length.  First, if the offset is not block aligned, read the first
 * block/extent, write from the buffer into it starting at offset, and write it back
 * out.  Next, for all the complete blocks/extents, in the range, write to them from
 * the buffer.  Finally, if there is more to write, read the last extent/buffer,
 * write from the buffer into the beginning of the block/extent, and write it out.
 * \par Note: Directory data does not appear to be cached. This could be a huge slowdown.
 * \par Warning:
 * \param psVolume	AFS filesystem pointer
 * \param psInode	AFS Inode to write to
 * \param pBuffer	Buffer to write from
 * \param nPos		Start position in file to write at
 * \param a_nSize	Number of octets to write
 * \return 0 on success, negative error code on failure
 * \sa
 *****************************************************************************/
int afs_do_write( AfsVolume_s * psVolume, AfsInode_s * psInode, const char *pBuffer, off_t nPos, size_t a_nSize )
{
	const int nBlockSize = psVolume->av_psSuperBlock->as_nBlockSize;
	int nSize = a_nSize;
	off_t nFirstBlock = nPos / nBlockSize;
	off_t nLastBlock =( nPos + nSize + nBlockSize - 1 ) / nBlockSize;
	off_t nNumBlocks = nLastBlock - nFirstBlock + 1;
	int nOffset = nPos % nBlockSize;
	off_t nBlockAddr;
	char *pBlock = NULL;
	int nRunLength;
	int nError;

	if( ( nPos + nSize ) > ( afs_get_inode_block_count( psInode ) * nBlockSize ) )
	{
		if( S_ISDIR( psInode->ai_nMode ) )
		{
			printk( "Panic: afs_do_write() dir to small!!\n" );
		}
		else
		{
			printk( "Panic: afs_do_write() file to small!!\n" );
		}
		return( -ENOSPC );
	}

	if( S_ISDIR( psInode->ai_nMode ) )
	{
		pBlock = afs_alloc_block_buffer( psVolume );
		if( pBlock == NULL )
		{
			printk( "Error: afs_do_write() no memory for data buffer\n" );
			return( -ENOMEM );
		}
	}

	nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );

	if( nError < 0 )
	{
		printk( "Error: afs_do_write() 1 afs_get_stream_blocks() failed with code %d\n", nError );
	}

	if( nError >= 0 && nOffset != 0 )
	{
		if( S_ISDIR( psInode->ai_nMode ) )
		{
			nError = afs_logged_read( psVolume, pBlock, nBlockAddr );
		}
		else
		{
			pBlock =( char * )get_cache_block( psVolume->av_nDevice, nBlockAddr, nBlockSize );
			if( pBlock == NULL )
			{
				nError = -EIO;
			}
		}
		if( nError >= 0 )
		{
			off_t nLen = min( nSize, nBlockSize - nOffset );

			memcpy( pBlock + nOffset, pBuffer, nLen );
			if( S_ISDIR( psInode->ai_nMode ) )
			{
				nError = afs_logged_write( psVolume, pBlock, nBlockAddr );
			}
			else
			{
				mark_blocks_dirty( psVolume->av_nDevice, nBlockAddr, 1 );
				release_cache_block( psVolume->av_nDevice, nBlockAddr );
			}
			if( nError >= 0 )
			{
				pBuffer += nLen;
				nSize -= nLen;
				nBlockAddr++;
				nFirstBlock++;
				nRunLength--;
				nNumBlocks--;
			}
		}
	}
	while( nSize >= nBlockSize && nError >= 0 )
	{
		off_t nLen;

		if( nRunLength == 0 )
		{
			nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );
			if( nError < 0 )
			{
				printk( "Error: afs_do_write() 2 afs_get_stream_blocks() failed with code %d\n", nError );
			}
		}
		if( nError >= 0 )
		{
			int i;

			nLen = min( nSize / nBlockSize, nRunLength );
			if( S_ISDIR( psInode->ai_nMode ) )
			{
				nError = 0;
				for( i = 0; i < nLen; ++i )
				{
					nError = afs_logged_write( psVolume, pBuffer, nBlockAddr );
					if( nError < 0 )
					{
						printk( "Error: afs_do_write() failed to write directory data block\n" );
						break;
					}
					nRunLength--;
					nNumBlocks--;
					nFirstBlock++;
					nBlockAddr++;
					nSize -= nBlockSize;
					pBuffer += nBlockSize;
					kassertw( nRunLength >= 0 );
					kassertw( nSize >= 0 );
				}
			}
			else
			{
				nError = cached_write( psVolume->av_nDevice, nBlockAddr, pBuffer, nLen, nBlockSize );
				if( nError >= 0 )
				{
					nRunLength -= nLen;
					nNumBlocks -= nLen;
					nFirstBlock += nLen;
					nBlockAddr += nLen;
					nSize -= nLen * nBlockSize;
					pBuffer += nLen * nBlockSize;

					kassertw( nRunLength >= 0 );
					kassertw( nSize >= 0 );
				}
			}
		}
	}
	if( nSize > 0 && nError >= 0 )
	{
		if( nRunLength == 0 )
		{
			nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );
			if( nError < 0 )
			{
				printk( "Error: afs_do_write() 3 afs_get_stream_blocks() failed with code %d\n", nError );
			}
		}
		if( nError >= 0 )
		{
			if( S_ISDIR( psInode->ai_nMode ) )
			{
				if( psInode->ai_sData.ds_nSize > ( nPos + a_nSize ) )
				{
					nError = afs_logged_read( psVolume, pBlock, nBlockAddr );
				}
			}
			else
			{
				if( psInode->ai_sData.ds_nSize > ( nPos + a_nSize ) )
				{
					pBlock =( char * )get_cache_block( psVolume->av_nDevice, nBlockAddr, nBlockSize );
				}
				else
				{
					pBlock =( char * )get_empty_block( psVolume->av_nDevice, nBlockAddr, nBlockSize );
				}
				if( pBlock == NULL )
				{
					nError = -EIO;
				}
			}
			kassertw( nSize < nBlockSize );
			if( nError >= 0 )
			{
				off_t nLen = min( nSize, nBlockSize );

				memcpy( pBlock, pBuffer, nSize );
				pBuffer += nLen;
				nSize -= nLen;
				if( S_ISDIR( psInode->ai_nMode ) )
				{
					nError = afs_logged_write( psVolume, pBlock, nBlockAddr );
					if( nError < 0 )
					{
						printk( "Error: afs_do_write() failed to write last partial block to directory\n" );
					}
				}
				else
				{
					mark_blocks_dirty( psVolume->av_nDevice, nBlockAddr, 1 );
					release_cache_block( psVolume->av_nDevice, nBlockAddr );
				}
			}
		}
	}

	if( S_ISDIR( psInode->ai_nMode ) )
	{
		afs_free_block_buffer( psVolume, pBlock );
	}

	if( nError >= 0 )
	{
		if( ( nPos + a_nSize ) > psInode->ai_sData.ds_nSize )
		{
			psInode->ai_sData.ds_nSize = nPos + a_nSize;
		}
		psInode->ai_nModifiedTime = get_real_time();
		psInode->ai_nFlags |= INF_WAS_WRITTEN | INF_STAT_CHANGED;
	}

	return( nError );
}
Ejemplo n.º 23
0
/** Create and insert a new Inode
 * \par Description:
 * Create in Inode with the given mode, flags, index type, and name, add it to the
 * given parent directory, and write it to the given volume.
 * \par Note:
 * \par Warning:
 * \param psVolume		AFS filesystem pointer
 * \param psParent		AFS Inode of directory to contain new Inode
 * \param nMode			Type of inode (normal file, directory, etc. S_IF*)
 * \param nFlags		Inode flags (INF_*)
 * \param nIndexType	Key type of index for inode (e_KeyType*)
 * \param pzName		Name of file associated with Inode
 * \param nNameLen		Length of pzName
 * \param ppsRes		Return argument for new Inode
 * \return 0 on success, negative error code on failure
 * \sa
 *****************************************************************************/
int afs_create_inode( AfsVolume_s * psVolume, AfsInode_s * psParent, int nMode, int nFlags, int nIndexType, const char *pzName, int nNameLen, AfsInode_s ** ppsRes )
{
	AfsSuperBlock_s *const psSuperBlock = psVolume->av_psSuperBlock;
	const int nBlockSize = psSuperBlock->as_nBlockSize;
	int nAllocGroup = 0;
	BIterator_s sIterator;
	BlockRun_s sInodeNum;
	off_t nInodeNum;
	AfsInode_s *psInode;
	int nError;


	if( NULL != psParent )
	{
		if( nNameLen <= 0 )
		{
			return( -EINVAL );
		}
		// FIXME: Check if names realy can be B_MAX_KEY_SIZE long(or do we need to subtract 1 like here)
		if( nNameLen >= B_MAX_KEY_SIZE )
		{
			return( -ENAMETOOLONG );
		}
		if( S_ISDIR( psParent->ai_nMode ) == false )
		{
			printk( "Error: afs_create_inode() parent is not a directory\n" );
			return( -ENOTDIR );
		}
		nError = bt_lookup_key( psVolume, psParent, pzName, nNameLen, &sIterator );
		if( 1 == nError )
		{
			return( -EEXIST );
		}
		else
		{
			if( nError < 0 )
			{
				printk( "Error : afs_create_inode() Failed to search parent for duplicate filenames %d\n", nError );
				return( nError );
			}
		}
		nAllocGroup = psParent->ai_sInodeNum.group + 8;
	}

	psInode = kmalloc( nBlockSize, MEMF_KERNEL | MEMF_CLEAR | MEMF_OKTOFAILHACK );

	if( psInode == NULL )
	{
		printk( "Error: afs_create_inode() no memory for inode\n" );
		return( -ENOMEM );
	}

	nError = afs_alloc_blocks( psVolume, &sInodeNum, NULL, nAllocGroup, 1, 1 );

	if( nError < 0 )
	{
		printk( "Error : Failed to alloc space for new inode %d\n", nError );
		kfree( psInode );
		return( nError );
	}
	nInodeNum = afs_run_to_num( psSuperBlock, &sInodeNum );

	memset( psInode, 0, nBlockSize );

	psInode->ai_nMagic1 = INODE_MAGIC;
	psInode->ai_sInodeNum = sInodeNum;
	psInode->ai_nUID = getfsuid();
	psInode->ai_nGID = getfsgid();
	psInode->ai_nMode = nMode;
	psInode->ai_nFlags = nFlags | INF_USED;
	psInode->ai_nIndexType = nIndexType;
	atomic_set( &psInode->ai_nLinkCount, 1 );
	psInode->ai_nCreateTime = get_real_time();
	psInode->ai_nModifiedTime = psInode->ai_nCreateTime;
	psInode->ai_nInodeSize = nBlockSize;

	if( psParent != NULL )
	{
		psInode->ai_sParent = psParent->ai_sInodeNum;
	}

	if( psParent != NULL )
	{
		nError = bt_insert_key( psVolume, psParent, pzName, nNameLen, nInodeNum );
		if( nError < 0 )
		{
			afs_free_blocks( psVolume, &sInodeNum );
			printk( "Error : Failed to insert new inode into parent %d\n", nError );
			kfree( psInode );
			return( nError );
		}
	}
	nError = afs_logged_write( psVolume, psInode, nInodeNum );

	if( nError >= 0 && ppsRes != NULL )
	{
		*ppsRes = psInode;
	}
	else
	{
		kfree( psInode );
	}
	return( nError );
}