Beispiel #1
0
int write_DEHT_pointers_table(DEHT *ht)
{
	int ret = DEHT_STATUS_FAIL;

	TRACE_FUNC_ENTRY();

	CHECK(NULL != ht);

	if (NULL == ht->hashTableOfPointersImageInMemory) {
		return DEHT_STATUS_NOT_NEEDED;
	}

	/* write the offset table */
	CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, KEY_FILE_OFFSET_TO_FIRST_BLOCK_PTRS(ht), (byte_t *) ht->hashTableOfPointersImageInMemory, KEY_FILE_FIRST_BLOCK_PTRS_SIZE(ht))));

	/* free the cache (according to the spec) */
	FREE(ht->hashTableOfPointersImageInMemory);

	ret = DEHT_STATUS_SUCCESS;
	goto LBL_CLEANUP;

LBL_ERROR:
	ret = DEHT_STATUS_FAIL;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	TRACE_FUNC_EXIT();
	return ret;
}
Beispiel #2
0
int add_DEHT ( DEHT *ht, const unsigned char *key, int keyLength, 
				 const unsigned char *data, int dataLength)
{
	int ret = DEHT_STATUS_FAIL;

	int hashTableIndex = 0;

	byte_t * blockContent = NULL;
	DEHT_DISK_PTR keyBlockOffset = 0;
	ulong_t freeIndex = 0;

	KeyFilePair_t * targetRec = NULL;

	TRACE_FUNC_ENTRY();

	CHECK(NULL != ht);
	CHECK(NULL != key);
	CHECK(NULL != data);

	/* calc hash for key */
	CHECK(NULL != ht->hashFunc);
	hashTableIndex = ht->hashFunc(key, keyLength, ht->header.numEntriesInHashTable);
	TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): bucket index=%#x\n", __FILE__, __LINE__, __FUNCTION__, hashTableIndex));

	blockContent = malloc(KEY_FILE_BLOCK_SIZE(ht));
	CHECK_MSG("malloc", (NULL != blockContent));
	CHECK(DEHT_allocEmptyLocationInBucket(ht, hashTableIndex, blockContent, KEY_FILE_BLOCK_SIZE(ht),
					     &keyBlockOffset, &freeIndex));

	TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): using block at %#x, index=%lu\n", __FILE__, __LINE__, __FUNCTION__, (uint_t) keyBlockOffset, freeIndex));

	targetRec = GET_N_REC_PTR_IN_BLOCK(ht, blockContent, freeIndex);

	/* calc validation key and fill in record */
	/*! Note: return value isn't checked since the spec does not include details regarding the key 
		  validation function interface */
	CHECK(NULL != ht->comparisonHashFunc);
	(void) ht->comparisonHashFunc(key, keyLength, targetRec->key);

	/* write payload to data file */
	CHECK(DEHT_addData(ht, data, dataLength, &(targetRec->dataOffset)));

	/* write updated block to disk */
	CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, keyBlockOffset, blockContent, KEY_FILE_BLOCK_SIZE(ht))));

	TRACE("block updated");

	ret = DEHT_STATUS_SUCCESS;
	goto LBL_CLEANUP;	

LBL_ERROR:
	ret = DEHT_STATUS_FAIL;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	FREE(blockContent);

	TRACE_FUNC_EXIT();
	return ret;
}
Beispiel #3
0
int DEHT_writeUserBytes(DEHT * ht)
{
	bool_t ret = DEHT_STATUS_FAIL;

	TRACE_FUNC_ENTRY();
	CHECK(NULL != ht);

	if ((NULL == ht->userBuf) || (0 == ht->header.numUnrelatedBytesSaved)) {
		ret = DEHT_STATUS_NOT_NEEDED;
		goto LBL_CLEANUP;
	}

	CHECK_MSG(ht->sDatafileName, (pfwrite(ht->dataFP, DATA_FILE_OFFSET_TO_USER_BYTES, ht->userBuf, ht->header.numUnrelatedBytesSaved)));

	/*! Note that unlink write_DEHT_pointers_table(), we DO NOT free the block here. Since this interface was
	    not dictated by the project spec, we chose what we found to be a more convenient interface for our use-case,
	    namely - only writing the data to disk, but not freeing the reference here !*/

	ret = DEHT_STATUS_SUCCESS;
	goto LBL_CLEANUP;

LBL_ERROR:
	ret = DEHT_STATUS_FAIL;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	TRACE_FUNC_EXIT();
	return ret;
}
Beispiel #4
0
void save_run_parameters(Dbptr db,Pf *pf)
{
	char *dir,*dfile;
	char filename[512];
	char *vm,*vm3d;
	int ierr;
	
	dir = pfget_string(pf,"pmelrun_archive_directory");
	if(dir==NULL)elog_die(0,"Parameter pmelrun_archive_directory not in parameter file\n");
	if(makedir(dir))
		elog_die(0,"makedir failed on directory %s\n",dir);
	dfile = pfget_string(pf,"pmel_run_name");

	
	vm = pfget_string(pf,"travel_time_model");
	vm3d=pfget_string(pf,"3Dreference_model");
	if( (vm==NULL) || (vm3d==NULL) )
		elog_die(0,"Missing required velocity model definitions\nCheck parameters travel_time model and 3Dreference_model\n");
	db = dblookup(db,0,"pmelruns",0,0);
	ierr=dbaddv(db,0,"pmelrun",dfile,
		"vmodel",vm,
		"vmodel3d",vm3d,
		"dir",dir,
		"dfile",dfile,0);
	if(ierr < 0) elog_die(0,
		   "dbaddv error on pmelrun table\nVerify schema extensions for dbpmel and that the pmel_run_name parameter is unique\n");

	strcpy(filename,dir);
	strcat(filename,"/");
	strcat(filename,dfile);
	if(pfwrite(filename,pf))
		elog_die(0,"pfwrite error for file %s\n",filename);
}
Beispiel #5
0
static PyObject *
python_pfwrite( PyObject *self, PyObject *args ) {
	char	*usage = "Usage: _stock._pfwrite( pfname, filename )\n";
	char	*pfname;
	char	*filename;
	Pf	*pf;
	char	errmsg[STRSZ];
	long	rc;

	if( ! PyArg_ParseTuple( args, "ss", &pfname, &filename ) ) {

		USAGE;

		return NULL;
	}

	if( ( pf = getPf( pfname ) ) == (Pf *) NULL ) {
		
		sprintf( errmsg, "Failure opening parameter file '%s'\n", pfname );

		raise_elog( ELOG_COMPLAIN, errmsg );

		return NULL;
	}

	rc = pfwrite( filename, pf );

	return Py_BuildValue( "i", rc );
}
Beispiel #6
0
static bool_t DEHT_findFirstBlockForBucketAndAlloc(DEHT * ht, ulong_t bucketIndex, DEHT_DISK_PTR * blockOffset)
{
	bool_t ret = FALSE;
	
	TRACE_FUNC_ENTRY();

	CHECK(NULL != ht);
	CHECK(NULL != blockOffset);
	CHECK(bucketIndex < ht->header.numEntriesInHashTable);


	CHECK(DEHT_findFirstBlockForBucket(ht, bucketIndex, blockOffset));

	/* if this is the very first block for this bucket, alloc a new one */
	if (0 == *blockOffset) {

		*blockOffset = DEHT_allocKeyBlock(ht);
		CHECK(0 != *blockOffset);

		/* if present, update first block cache */
		if (NULL != ht->hashTableOfPointersImageInMemory) {
			/* update cache ptr */
			ht->hashTableOfPointersImageInMemory[bucketIndex] = *blockOffset;
		}
		else {
			/* update on-disk ptr */
			CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, KEY_FILE_OFFSET_TO_FIRST_BLOCK_PTRS(ht) + bucketIndex * sizeof(DEHT_DISK_PTR), (byte_t *) blockOffset, sizeof(*blockOffset))));
		}

		/* if present, update last block cache */
		if (NULL != ht->hashPointersForLastBlockImageInMemory) {
			ht->hashPointersForLastBlockImageInMemory[bucketIndex] = *blockOffset;
		}
	}

	ret = TRUE;
	goto LBL_CLEANUP;

LBL_ERROR:
	*blockOffset = 0;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	TRACE_FUNC_EXIT();
	return ret;
}
ESR_ReturnCode SR_EventLog_AudioWrite(SR_EventLog* self, void* buffer, size_t num_bytes)
{
  SR_EventLogImpl *impl = (SR_EventLogImpl*) self;
  ESR_ReturnCode rc;
  size_t size = num_bytes / impl->waveform_bytes_per_sample;

  if (num_bytes > 0 && pfwrite(buffer, impl->waveform_bytes_per_sample, size, impl->waveformFile) != size)
  {
    LCHAR cwd[P_PATH_MAX];
    size_t len;

    len = P_PATH_MAX;
    CHKLOG(rc, pf_get_cwd (cwd, &len));
    PLogError(L("ESR_WRITE_ERROR: %s, cwd=%s"), impl->waveformFilename, cwd);
    return ESR_WRITE_ERROR;
  }

  impl->waveform_num_bytes += num_bytes;
  return ESR_SUCCESS;
CLEANUP:
  return rc;
}
Beispiel #8
0
bool PStreamFile::write(pUint32 nbytes, pUint32& bytesWritten, const pUint8* buffer)
{
    if (m_file == P_NULL)
    {
        return false;
    }

    pUint32 tempBytesWritten = 0;
    pUint32 bytesRemaining = nbytes;
    const pUint8* p = buffer;

    do
    {
        tempBytesWritten = pfwrite(p, sizeof(pUint8), bytesRemaining, m_file);
        bytesRemaining -= tempBytesWritten;
        p += tempBytesWritten;
    } while (bytesRemaining && tempBytesWritten);

    bytesWritten = nbytes - bytesRemaining;

    return true;
}
ESR_ReturnCode SR_NametagsSaveImpl(SR_Nametags* self, const LCHAR* filename)
{
  SR_NametagsImpl* impl = (SR_NametagsImpl*) self;
  ESR_ReturnCode rc;
  PFile* file = NULL;
  size_t size, i;
  HashMap* nametags = impl->value;
  SR_NametagImpl* nametag;
  LCHAR* id;
  size_t len;
  LCHAR devicePath[P_PATH_MAX];
#define NAMETAG_LENGTH 200
  LCHAR nametagBuffer[NAMETAG_LENGTH];
  LCHAR number[MAX_UINT_DIGITS+1];
#define NAMETAGID_LENGTH 20
  /* "token\0" == 6 */
#define TOKEN_LENGTH 6 + NAMETAGID_LENGTH
  LCHAR tokenName[TOKEN_LENGTH];
  size_t num_written;

  if (filename == NULL)
  {
    rc = ESR_INVALID_STATE;
    PLogError(ESR_rc2str(rc));
    goto CLEANUP;
  }
  size = P_PATH_MAX;
  CHKLOG(rc, ESR_SessionGetLCHAR(L("cmdline.nametagPath"), devicePath, &size));

  if (LSTRNCMP(filename, devicePath, LSTRLEN(devicePath)) != 0)
    LSTRCAT(devicePath, filename);
  else
    LSTRCPY(devicePath, filename);

  file = pfopen ( devicePath, L("w"));
/*  CHKLOG(rc, PFileSystemCreatePFile(devicePath, ESR_TRUE, &file));
  CHKLOG(rc, file->open(file, L("w")));*/
  CHKLOG(rc, nametags->getSize(nametags, &size));

  if ( file == NULL )
    goto CLEANUP;

  for (i = 0; i < size; ++i)
  {
    CHKLOG(rc, nametags->getValueAtIndex(nametags, i, (void **)&nametag));

    CHKLOG(rc, nametag->Interface.getID(&nametag->Interface, &id));

    if (LSTRLEN(id) + 1 + LSTRLEN(nametag->value) + 2 >= NAMETAG_LENGTH)
    {
      rc = ESR_BUFFER_OVERFLOW;
      PLogError(ESR_rc2str(rc));
      goto CLEANUP;
    }
    psprintf(nametagBuffer, L("%s %s\n"), id, nametag->value);
    len = LSTRLEN(nametagBuffer);
/*    CHKLOG(rc, file->write(file, nametagBuffer, sizeof(LCHAR), &len));*/
    num_written = pfwrite ( nametagBuffer, sizeof ( LCHAR ), len, file );

    if ( num_written != len )
        goto CLEANUP;

    if (LSTRLEN(id) > NAMETAGID_LENGTH)
    {
      rc = ESR_BUFFER_OVERFLOW;
      PLogError(ESR_rc2str(rc));
      goto CLEANUP;
    }
    psprintf(tokenName, L("nametag[%s]"), id);
    CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, tokenName, nametag->value));
  }
  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("filename"), filename));
  len = MAX_UINT_DIGITS + 1;
  CHKLOG(rc, lultostr(size, (LCHAR*) &number, &len, 10));
  CHKLOG(rc, SR_EventLogToken_BASIC(impl->eventLog, impl->logLevel, L("saveCount"), number));
  CHKLOG(rc, SR_EventLogEvent_BASIC(impl->eventLog, impl->logLevel, L("SR_NametagsSave")));
  pfclose (file);
  return ESR_SUCCESS;
CLEANUP:
  if (file != NULL)
    pfclose (file);
  return rc;
}
ESR_ReturnCode writeRiffHeader(SR_EventLog* self)
{
  SR_EventLogImpl *impl = (SR_EventLogImpl *)self;
  unsigned int total_buflen;
  int num_samples;
  unsigned int bytes_sec;

  RiffHeaderStruct header;

  num_samples = impl->waveform_num_bytes / impl->waveform_bytes_per_sample;

  strncpy(header.riffString, "RIFF", 4);
  strncpy(header.waveString, "WAVE", 4);
  strncpy(header.fmtString, "fmt ", 4);
  strncpy(header.dataString, "data", 4);

  total_buflen = sizeof(RiffHeaderStruct) + impl->waveform_num_bytes;
  bytes_sec = impl->waveform_sample_rate * impl->waveform_bytes_per_sample;

  header.riffChunkLength = total_buflen - sizeof(ChunkInfoStruct);
  header.fmtChunkLength = sizeof(WaveFormat);
  header.waveinfo.nFormatTag = WAVEFORMAT_PCM;  /* codec */
  header.waveinfo.nChannels = 1;
  header.waveinfo.nSamplesPerSec = impl->waveform_sample_rate;
  header.waveinfo.nAvgBytesPerSec = bytes_sec;
  header.waveinfo.nBlockAlign = (unsigned short) impl->waveform_bytes_per_sample;
  header.waveinfo.wBitsPerSample = (unsigned short)((bytes_sec * 8) / impl->waveform_sample_rate);
  header.dataLength = (unsigned int) impl->waveform_num_bytes;

  pfseek(impl->waveformFile, 0, SEEK_SET);

  /* RiffHeaderStruct */
  pfwrite(&header.riffString, 1, sizeof(header.riffString), impl->waveformFile);
  pfwrite(&header.riffChunkLength, sizeof(header.riffChunkLength), 1, impl->waveformFile);
  pfwrite(&header.waveString, 1, sizeof(header.waveString), impl->waveformFile);
  pfwrite(&header.fmtString, 1, sizeof(header.fmtString), impl->waveformFile);
  pfwrite(&header.fmtChunkLength, sizeof(header.fmtChunkLength), 1, impl->waveformFile);

  /* WaveFormat */
  pfwrite(&header.waveinfo.nFormatTag, sizeof(header.waveinfo.nFormatTag), 1, impl->waveformFile);
  pfwrite(&header.waveinfo.nChannels, sizeof(header.waveinfo.nChannels), 1, impl->waveformFile);
  pfwrite(&header.waveinfo.nSamplesPerSec, sizeof(header.waveinfo.nSamplesPerSec), 1, impl->waveformFile);
  pfwrite(&header.waveinfo.nAvgBytesPerSec, sizeof(header.waveinfo.nAvgBytesPerSec), 1, impl->waveformFile);
  pfwrite(&header.waveinfo.nBlockAlign, sizeof(header.waveinfo.nBlockAlign), 1, impl->waveformFile);
  pfwrite(&header.waveinfo.wBitsPerSample, sizeof(header.waveinfo.wBitsPerSample), 1, impl->waveformFile);

  /* Continuation of RiffHeaderStruct */
  pfwrite(&header.dataString, 1, sizeof(header.dataString), impl->waveformFile);
  pfwrite(&header.dataLength, sizeof(header.dataLength), 1, impl->waveformFile);

  return ESR_SUCCESS;
}
ESR_ReturnCode logIt(SR_EventLogImpl *impl, LCHAR* evtt, LCHAR* log_record, size_t* writtenSize)
{
  struct tm *ct, ct_r;
  LCHAR header[128], header2[64];
  PTimeStamp timestamp;
  const size_t sizeof_LCHAR = sizeof(LCHAR);
  const LCHAR* bar = "|";
  const LCHAR* nl = "\n";
  size_t i, len;
  const LCHAR* toWrite[5];

  toWrite[0] = header;
  toWrite[1] = bar;
  toWrite[2] = evtt;
  toWrite[3] = log_record;
  toWrite[4] = nl;

  ct = &ct_r;
  memset(ct, 0, sizeof(struct tm));

  switch (impl->logFile_state)
  {
    case FILE_OK:
    case SPACE_SETTING:
      PTimeStampSet(&timestamp);
      ct = localtime_r(&timestamp.secs, &ct_r);

      sprintf(header, "TIME=%04d%02d%02d%02d%02d%02d%03d",
              ct->tm_year + 1900, ct->tm_mon + 1, ct->tm_mday, ct->tm_hour,
              ct->tm_min, ct->tm_sec, timestamp.msecs);
      quote_delimiter(header, 128);

      sprintf(header2, "CHAN=%s", L("0")); /* default is channel 0 in ESR */
      quote_delimiter(header2, 128);

      LSTRCAT(header, bar);
      LSTRCAT(header, header2);

      /* write the header,bar,evtt, and record */
      for (*writtenSize = 0, i = 0; i < 5; i++)
      {
        len = LSTRLEN(toWrite[i]);
        if (pfwrite(toWrite[i], sizeof_LCHAR, len, impl->logFile))
          *writtenSize += len;
      }

      if (*writtenSize <= 0)
      {
        PLogError(L("Could not write to log file; logging halted"));
        impl->logFile_state = FILE_ERROR;
        break;
      }
      else
      {
        pfflush(impl->logFile);
      }

      break;

      /* If couldn't open file or error previously, just return */
    case UNINITIALIZED:
    case NO_FILE:
    case FILE_ERROR:
    case SEEK_ERROR:
    default:
      return ESR_INVALID_STATE;

  }

  return ESR_SUCCESS;
}
/* This little routine dumps the parameter space of pf and the output
tbls of ggnloc to a log file tagged by orid.  Note, however, that
if ggnloc failed for some reason, it is assumed that orid will be set
to a NEGATIVE number.  When this occurs, the results are written to 
a "failures" directory defined in rtopts.  

IMPORTANT:  multiple instances of orbgenloc should arrange to write
in seperate failure directories or they can collide.  
*/
int write_to_logfile(RTlocate_Options rtopts, int orid, int evid,
	Pf *pf, Tbl *converge_history, Tbl *reason_converged,Tbl *residual)
{
	char fname[256];
	FILE *fp;
	/* We write the logfile output as a pf object copying
	code from sgnloc */
	Pf *pflog;
	Tbl *t;  /* formatted output tbl of hypo convergence history */
	char *line; 
	int i;
	Hypocenter *hypos;

	/* This can fail for very long directory entries, but it
	isn't worth messing with in my mind.  Note switch for 
	orid */
	if(orid > 0)
	{
		sprintf(fname,"%s/orid%d.pf",rtopts.logdir,orid);
	}
	else
	{
		sprintf(fname,"%s/%s/evid%d.pf",rtopts.logdir,
			rtopts.failure_sdir,evid);
	}
	pfwrite(fname,pf);

	/* Here we encapsulate the convergence history information into
	a second pf object, and write this onto the same pf file */
        t = newtbl(maxtbl(converge_history));
        for(i=0;i<maxtbl(converge_history);++i)
        {
                hypos = (Hypocenter *)gettbl(converge_history,i);
                line = format_hypo(hypos);
                pushtbl(t,line);
        }
        pflog = pfnew(PFFILE);
        pfput_tbl(pflog,"convergence_history",t);
  
        printf("Reasons for convergence:\n");
        for(i=0;i<maxtbl(reason_converged);++i)
                printf("%s\n",gettbl(reason_converged,i));
        pfput_tbl(pflog,"convergence_criteria",reason_converged);
        pfput_tbl(pflog,"residuals",residual);
	/* We use pf2string rather than pfwrite since I'm not 
	sure what pfwrite will do when the file already exists. 
	Here we just append the new pf info to the end of the
	stuff written above. */
	if((fp=fopen(fname,"a")) == NULL)
	{
		elog_complain(1,"Cannot open log file %s\n",fname);
		return(1);
	}
	fseek(fp,0L,SEEK_END);
        line = pf2string(pflog);
	fwrite(line,1,strlen(line),fp);
	fclose(fp);
	free(line);
	pffree(pflog);
	freetbl(t,free);
	return(0);	
}
Beispiel #13
0
int insert_uniquely_DEHT ( DEHT *ht, const unsigned char *key, int keyLength, 
				 const unsigned char *data, int dataLength)
{
	int ret = DEHT_STATUS_FAIL;

	byte_t * tempKeyBlock = NULL;
	DEHT_DISK_PTR keyBlockDiskOffset = 0;
	ulong_t keyIndex = 0;
	
	KeyFilePair_t * targetRecord = NULL;
	DEHT_DISK_PTR newDataOffset = 0;
	
	byte_t tempData[DEHT_MAX_DATA_LEN] = {0};

	TRACE_FUNC_ENTRY();

	CHECK(NULL != ht);
	CHECK(NULL != key);
	CHECK(NULL != data);

	/* allocate a buffer for DEHT_queryEx */
	tempKeyBlock = malloc(KEY_FILE_BLOCK_SIZE(ht));
	CHECK_MSG("malloc", (NULL != tempKeyBlock));
	
	ret = DEHT_queryEx(ht, key, keyLength, tempData, sizeof(tempData), tempKeyBlock, KEY_FILE_BLOCK_SIZE(ht), 
				  &keyBlockDiskOffset, &keyIndex);

	switch(ret) {
	case DEHT_STATUS_NOT_NEEDED:
		TRACE("simple insert");
		/* not found - just insert */
		CHECK(DEHT_STATUS_SUCCESS == add_DEHT (ht, key, keyLength, data, dataLength));

		ret = DEHT_STATUS_SUCCESS;

		break;

	case DEHT_STATUS_FAIL:
	default:
		if (0 >= ret) {
			/* internal error */
			goto LBL_ERROR;
		}


		/* if we got here, the key was found */
		TRACE_FPRINTF((stderr, "TRACE: %s:%d (%s): key already in DEHT. Updating record at %#x\n", __FILE__, __LINE__, __FUNCTION__, (uint_t) keyBlockDiskOffset));

		/* update data in the data file */
		CHECK(DEHT_addData(ht, data, dataLength, &newDataOffset)); 

		/* get the key record */
		targetRecord = GET_N_REC_PTR_IN_BLOCK(ht, tempKeyBlock, keyIndex);
		/* update key record */
		targetRecord->dataOffset = newDataOffset;

		/* update block on disk */
		CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, keyBlockDiskOffset, tempKeyBlock, KEY_FILE_BLOCK_SIZE(ht))));

		ret = DEHT_STATUS_NOT_NEEDED;
		
		break;
	}

	goto LBL_CLEANUP;	

LBL_ERROR:
	ret = DEHT_STATUS_FAIL;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	FREE(tempKeyBlock);

	TRACE_FUNC_EXIT();
	return ret;
}
Beispiel #14
0
static bool_t DEHT_allocEmptyLocationInBucket(DEHT * ht, ulong_t bucketIndex,
					     byte_t * blockDataOut, ulong_t blockDataLen,
					     DEHT_DISK_PTR * blockDiskPtr, ulong_t * firstFreeIndex)
{
	bool_t ret = FALSE;

	DEHT_DISK_PTR newBlock = 0;

	TRACE_FUNC_ENTRY();

	CHECK(NULL != ht);
	CHECK(bucketIndex < ht->header.numEntriesInHashTable);
	CHECK(NULL != blockDataOut);
	CHECK(KEY_FILE_BLOCK_SIZE(ht) <= blockDataLen);
	CHECK(NULL != blockDiskPtr);
	CHECK(NULL != firstFreeIndex);

	CHECK(DEHT_findLastBlockForBucket(ht, bucketIndex, blockDiskPtr));
	if (0 == *blockDiskPtr) {
		/* if this is the first ever block, call DEHT_findFirstBlockForBucketAndAlloc() which will also alloc the first block */
		CHECK(DEHT_findFirstBlockForBucketAndAlloc(ht, bucketIndex, blockDiskPtr));
		CHECK(0 != *blockDiskPtr);
	}

	/* read it */
	CHECK_MSG(ht->sKeyfileName, (pfread(ht->keyFP, *blockDiskPtr, blockDataOut, KEY_FILE_BLOCK_SIZE(ht))));

	/* get the current used block count */
	*firstFreeIndex = GET_USED_RECORD_COUNT(blockDataOut);
	
	/* see if this block is full */
	if (*firstFreeIndex >= ht->header.nPairsPerBlock) {
	
		newBlock = DEHT_allocKeyBlock(ht);
		CHECK(0 != newBlock);

		/* update old block */
		SET_NEXT_BLOCK_PTR(ht, blockDataOut, newBlock);
	
		/* update last block reference if cache is present */
		if (NULL != ht->hashPointersForLastBlockImageInMemory) {
			ht->hashPointersForLastBlockImageInMemory[bucketIndex] = newBlock;
		}
		
		CHECK_MSG(ht->sKeyfileName, (pfwrite(ht->keyFP, *blockDiskPtr, blockDataOut, KEY_FILE_BLOCK_SIZE(ht))));
		
		/* now, just return the reference to the start of the new block */
		memset(blockDataOut, 0, KEY_FILE_BLOCK_SIZE(ht));
		*blockDiskPtr = newBlock;
		*firstFreeIndex = 0;
	}

	/* increase used pairs count by one. If & when the user will update the block on disk, this will be updated as well */
	SET_USED_RECORD_COUNT(blockDataOut, GET_USED_RECORD_COUNT(blockDataOut) + 1);

	ret = TRUE;
	goto LBL_CLEANUP;

LBL_ERROR:
	*blockDiskPtr = 0;
	*firstFreeIndex = 0;
	ret = FALSE;
	TRACE_FUNC_ERROR();

LBL_CLEANUP:
	TRACE_FUNC_EXIT();
	return ret;
}