void KVRecordStore::KVRecordCursor::_setCursor(const RecordId id) {
        // We should no cursor at this point, either because we're getting newly
        // constructed or because we're recovering from saved state (and so
        // the old cursor needed to be dropped).
        invariant(!_cursor);
        _cursor.reset();
        _savedLoc = RecordId();
        _savedVal = Slice();

        // A new iterator with no start position will be either min() or max()
        invariant(id.isNormal() || id == RecordId::min() || id == RecordId::max());
        const int dir = _isForward ? 1 : -1;
        _cursor.reset(_db->getCursor(_txn, Slice::of(KeyString(id)), dir));
    }
    RecordData KVRecordStore::_getDataFor(const KVDictionary *db, OperationContext* txn, const RecordId& id, bool skipPessimisticLocking) {
        Slice value;
        Status status = db->get(txn, Slice::of(KeyString(id)), value, skipPessimisticLocking);
        if (!status.isOK()) {
            if (status.code() == ErrorCodes::NoSuchKey) {
                return RecordData(nullptr, 0);
            } else {
                log() << "storage engine get() failed, operation will fail: " << status.toString();
                uasserted(28922, status.toString());
            }
        }

        // Return an owned RecordData that uses the SharedBuffer from `value'
        return RecordData(std::move(value.ownedBuf()), value.size());
    }
Exemple #3
0
Param_t *GetParam(int argc, const char **argv)
/* 
!C******************************************************************************

!Description: 'GetParam' sets up the 'param' data structure and populate with user
 parameters, either from the command line or from a parameter file.
 
!Input Parameters:
 argc           number of command line arguments
 argv           command line argument list

!Output Parameters:
 (returns)      'param' data structure or NULL when an error occurs

!Team Unique Header:

!END****************************************************************************
*/
{
  Param_t *this;
  char *error_string = NULL;
  FILE *fp;
  Key_t key;
  int len;
  char line[MAX_STR_LEN + 1];
  char temp[MAX_STR_LEN + 1];
  Param_key_t param_key;
  char *param_file_name;
  bool got_start, got_end;

  if (argc < 2) 
    RETURN_ERROR("no command line parameter", "GetParam", NULL);
  if (argc > 3) 
    RETURN_ERROR("too many command line parameters", "GetParam", NULL);
  if (strlen(argv[1]) < 1)
    RETURN_ERROR("no parameter file name", "GetParam", NULL);
  param_file_name = (char *)argv[1];

  /* Open the parameter file */
  if ((fp = fopen(param_file_name, "r")) == NULL)
    RETURN_ERROR("unable to open parameter file", "GetParam", NULL);

  /* Create the Param data structure */
  this = (Param_t *)malloc(sizeof(Param_t));
  if (this == NULL) {
    fclose(fp);
    RETURN_ERROR("allocating Input structure", "GetParam", NULL);
  }

  /* set default parameters */
  this->param_file_name         = NULL;
  this->input_xml_file_name     = NULL;
  this->LEDAPSVersion           = NULL;

  /* Populate the data structure */
  this->param_file_name = DupString(param_file_name);
  if (this->param_file_name == NULL)
    error_string = "duplicating parameter file name";

  if (error_string != NULL) {
    free(this->param_file_name);
    this->param_file_name = NULL;
    FreeParam(this);
    RETURN_ERROR(error_string, "GetParam", NULL);
  }

  /* Parse the header file */
  got_start = got_end = false;

  while((len = GetLine(fp, line)) > 0) {

    if (!StringParse(line, &key)) {
      sprintf(temp, "parsing header file; line = %s", line);
      error_string = temp;
      break;
    }
    if (key.len_key <= 0) continue;
    if (key.key[0] == '#') continue;

    param_key = (Param_key_t) KeyString(key.key, key.len_key, Param_string, 
       (int)PARAM_NULL, (int)PARAM_MAX);
    if (param_key == PARAM_NULL) {
      key.key[key.len_key] = '\0';
      sprintf(temp, "invalid key; key = %s", key.key);
      error_string = temp;
      break;
    }
    if (!got_start) {
      if (param_key == PARAM_START) {
        if (key.nval != 0) {
          error_string = "no value expected (start key)";
          break;
        }
        got_start = true;
        continue;
      } else {
        error_string  = "no start key in parameter file";
        break;
      }
    }

    /* Get the value for each keyword */
    switch (param_key) {

      case PARAM_XML_FILE:
        if (key.nval <= 0) {
          error_string = "no input XML metadata file name";
          break; 
        } else if (key.nval > 1) {
          error_string = "too many input XML metadata file names";
          break; 
        }
        if (key.len_value[0] < 1) {
          error_string = "no input XML metadata file name";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->input_xml_file_name = DupString(key.value[0]);
        if (this->input_xml_file_name == NULL) {
          error_string = "duplicating input XML metadata file name";
          break;
        }
        break;

      case PARAM_LEDAPSVERSION:
        if (key.nval <= 0) {
          error_string = "no LEDAPSVersion number";
          break;
        } else if (key.nval > 1) {
          error_string = "too many LEDAPSVersion numbers";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no LEDAPSVersion number";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->LEDAPSVersion = DupString(key.value[0]);
        if (this->LEDAPSVersion == NULL) {
          error_string = "duplicating LEDAPSVersion number";
          break;
        }
        break;

      case PARAM_END:
        if (key.nval != 0) {
          error_string = "no value expected (end key)";
          break; 
        }
        got_end = true;
        break;

      default:
        error_string = "key not implmented";
    }
    if (error_string != NULL) break;
    if (got_end) break;
  }

  /* Close the parameter file */
  fclose(fp);

  if (error_string == NULL) {
    if (!got_start) 
      error_string = "no start key in header";
    else if (!got_end)
      error_string = "no end key in header";
  }

  /* Handle null values */
  if (error_string == NULL) {
    if (this->input_xml_file_name == NULL) 
      error_string = "no input XML metadata file name given";
    if (this->LEDAPSVersion == NULL)
      error_string = "no LEDAPS Version given";
  }

  /* Handle errors */
  if (error_string != NULL) {
    free(this->param_file_name);
    free(this->input_xml_file_name);
    free(this->LEDAPSVersion);
    free(this);
    RETURN_ERROR(error_string, "GetParam", NULL);
  }
  
  return this;
}
Exemple #4
0
Param_t *GetParam(int argc, const char **argv)
/* 
!C******************************************************************************

!Description: 'GetParam' sets up the 'param' data structure and populate with user
 parameters, either from the command line or from a parameter file.
 
!Input Parameters:
 argc           number of command line arguments
 argv           command line argument list

!Output Parameters:
 (returns)      'param' data structure or NULL when an error occurs

!Team Unique Header:

 ! Design Notes:
   1. An error status is returned when:
       a. memory allocation is not successful
       b. an error is returned from the ReadCmdLine function
       c. certain required parameters are invalid or not entered:
            input file name, output file name, geolocation file name,
	    SDS name, output space projection number, 
	    output space pixel size, output space upper left corner, 
	    output space image size, either output space sphere or projection
	    parameter number 0
	    output space zone number not given for UTM
       d. the input is 'GRID_SPACE' then and certain required parameters 
          are invalid or not entered:
	    input space projection number, input space pixel size, 
	    input space upper left corner, either input space sphere or 
	    projection parameter number 0
       e. the input is 'GRID_SPACE' and the geolocation file name is given
       f. the resampling kernel is 'USER_KERNEL' and the kernel file name 
          is invalid or not entered.
   2. Error of type 'a' are handled with the 'RETURN_ERROR' macro and 
      the others are handled by writting the error messages to 'stderr' and 
      then printing the usage information.
   3. 'FreeParam' should be called to deallocate memory used by the 
      'param' data structures.

!END****************************************************************************
*/
{
  Param_t *this;
  char *error_string = (char *)NULL;
  FILE *fp;
  Key_t key;
  int len;
  char line[MAX_STR_LEN + 1];
  char temp[MAX_STR_LEN + 1];
  Param_key_t param_key;
  char *param_file_name;
  int itemp;
  bool got_start, got_end;

  if (argc < 2) 
    RETURN_ERROR("no command line parameter", "GetParam", 
                 (Param_t *)NULL);
  if (argc > 3) 
    RETURN_ERROR("too many command line parameters", "GetParam", 
                 (Param_t *)NULL);
  if (strlen(argv[1]) < 1)
    RETURN_ERROR("no paramter file name", "GetParam", 
                 (Param_t *)NULL);
  param_file_name = (char *)argv[1];

  /* Open the parameter file */
  
  if ((fp = fopen(param_file_name, "r")) == (FILE *)NULL)
    RETURN_ERROR("unable to open parameter file", "GetParam", 
                 (Param_t *)NULL);

  /* Create the Param data structure */

  this = (Param_t *)malloc(sizeof(Param_t));
  if (this == (Param_t *)NULL) {
    fclose(fp);
    RETURN_ERROR("allocating Input structure", "GetParam", 
                 (Param_t *)NULL);
  }

  /* set default parameters */

  this->param_file_name  = (char *)NULL;
  this->input_file_name  = (char *)NULL;
  this->input_therm_file_name  = (char *)NULL;
  this->lut_file_name    = (char *)NULL;
  this->output_file_name = (char *)NULL;
  this->PGEVersion              = (char *)NULL;
  this->ProcessVersion          = (char *)NULL;
  this->therm_flag  = false;
  this->apply_kernel =  0;
  this->ksize =         0;
  this->sieve_thresh =  0;

  /* Populate the data structure */

  this->param_file_name = DupString(param_file_name);
  if (this->param_file_name == (char *)NULL)
    error_string = "duplicating parameter file name";

  if (error_string == (char *)NULL) {
    this->lut_file_name = DupString(LUT_FILE_NAME);
    if (this->lut_file_name == (char *)NULL)
      error_string = "duplicating lookup table file name";
  }

  if (error_string != (char *)NULL) {
    if (this->param_file_name != (char *)NULL) 
      free(this->param_file_name);
    if (this->lut_file_name != (char *)NULL) 
      free(this->lut_file_name);
    FreeParam(this);
    RETURN_ERROR(error_string, "GetParam", (Param_t *)NULL);
  }

  /* Parse the header file */

  got_start = got_end = false;

  while((len = GetLine(fp, line)) > 0) {

    if (!StringParse(line, &key)) {
      sprintf(temp, "parsing header file; line = %s", line);
      error_string = temp;
      break;
    }
    if (key.len_key <= 0) continue;
    if (key.key[0] == '#') continue;

    param_key = (Param_key_t)
       KeyString(key.key, key.len_key, Param_string, 
		 (int)PARAM_NULL, (int)PARAM_MAX);
    if (param_key == PARAM_NULL) {
      key.key[key.len_key] = '\0';
      sprintf(temp, "invalid key; key = %s", key.key);
      error_string = temp;
      break;
    }
    if (!got_start) {
      if (param_key == PARAM_START) {
        if (key.nval != 0) {
	  error_string = "no value expected (start key)";
	  break;
	}
        got_start = true;
	continue;
      } else {
        error_string  = "no start key in parameter file";
        break;
      }
    }

    /* Get the value for each keyword */

    switch (param_key) {

      case PARAM_REF_FILE:
        if (key.nval <= 0) {
	  error_string = "no reflectance file name";
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many reflectance file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
	  error_string = "no reflectance file name";
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->input_file_name = DupString(key.value[0]);
	if (this->input_file_name == (char *)NULL) {
	  error_string = "duplicating reflectance file name";
	  break;
        }
        break;

      case PARAM_THERM_FILE:
        if (key.nval <= 0) {
          printf("warning %s \n","no band6 file name"); 
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many band6 file names";
          printf("error_string=(%s)\n",error_string); 
	  break; 
	}
	if (key.len_value[0] < 1) {
          printf("warning %s \n","no band6 file name"); 
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->input_therm_file_name = DupString(key.value[0]);
        this->therm_flag  = true;
	if (this->input_file_name == (char *)NULL) {
	  error_string = "duplicating band6 file name";
	  break;
        }
        break;

      case PARAM_CSM_FILE:
        if (key.nval <= 0) {
	  error_string = "no CLoud Mask file name";
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many Cloud Mask file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
	  error_string = "no Cloud Mask file name";
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->output_file_name = DupString(key.value[0]);
	if (this->output_file_name == (char *)NULL) {
	  error_string = "duplicating Cloud Mask file name";
	  break;
        }
        break;

      case PARAM_CSM_FILTER:
        if (key.nval <= 0) {
	  break; 
	} else if (key.nval > 3) {
	  error_string = "too many filter values";
	  break; 
	}
	if (key.len_value[0] < 1) {
	  break;
	}
	if (key.nval > 0)
	  {
          key.value[0][key.len_value[0]] = '\0';
          this->ksize = atoi(key.value[0]);
          this->apply_kernel = 1;
	  }
	if (key.nval > 1)
	  {
          key.value[1][key.len_value[1]] = '\0';
          itemp = atoi(key.value[1]);
          if ( itemp > this->apply_kernel )this->apply_kernel = itemp;
	  }
	if (key.nval > 2)
	  {
          key.value[2][key.len_value[2]] = '\0';
          this->sieve_thresh= atoi(key.value[2]);
	  }
        break;

      case PARAM_PGEVERSION:
        if (key.nval <= 0) {
          error_string = "no PGEVersion number";
          break;
        } else if (key.nval > 1) {
          error_string = "too many PGEVersion numbers";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no PGEVersion number";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->PGEVersion = DupString(key.value[0]);
        if (this->PGEVersion == (char *)NULL) {
          error_string = "duplicating PGEVersion number";
          break;
        }
        break;

      case PARAM_PROCESSVERSION:
        if (key.nval <= 0) {
          error_string = "no ProcessVersion number";
          break;
        } else if (key.nval > 1) {
          error_string = "too many ProcessVersion numbers";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no ProcessVersion number";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->ProcessVersion = DupString(key.value[0]);
        if (this->ProcessVersion == (char *)NULL) {
          error_string = "duplicating ProcessVersion number";
          break;
        }
        break;

      case PARAM_END:
        if (key.nval != 0) {
	  error_string = "no value expected (end key)";
	  break; 
	}
        got_end = true;
        break;

      default:
        error_string = "key not implmented";

    }
    if (error_string != (char *)NULL) break;
    if (got_end) break;

  }

  /* Close the parameter file */

  fclose(fp);

  if (error_string == (char *)NULL) {
    if (!got_start) 
      error_string = "no start key in header";
    else if (!got_end)
      error_string = "no end key in header";
  }

  /* Handle null values */
  
  if (error_string == (char *)NULL) {
    if (this->input_file_name == (char *)NULL) 
      error_string = "no input file name given";
    if (this->lut_file_name == (char *)NULL) 
      error_string = "no lookup table file name given";
    if (this->output_file_name == (char *)NULL) 
      error_string = "no output file name given";
    if (this->PGEVersion == (char *)NULL)
      error_string = "no PGE Version given";
    if (this->ProcessVersion == (char *)NULL)
      error_string = "no Process Version given";
  }

  /* Handle errors */

  if (error_string != (char *)NULL) {
    if (this->param_file_name != (char *)NULL) 
      free(this->param_file_name);
    if (this->input_file_name != (char *)NULL) 
      free(this->input_file_name);
    if (this->lut_file_name != (char *)NULL) 
      free(this->lut_file_name);
    if (this->output_file_name != (char *)NULL) 
      free(this->output_file_name);
    if (this->PGEVersion != (char *)NULL)
      free(this->PGEVersion);
    if (this->ProcessVersion != (char *)NULL)
      free(this->ProcessVersion);
    if (this != (Param_t *)NULL) free(this);
    RETURN_ERROR(error_string, "GetParam", (Param_t *)NULL);
  }
  
  return this;
}
    void KVRecordStoreCapped::deleteAsNeeded(OperationContext *txn) {
        if (!needsDelete(txn)) {
            // nothing to do
            return;
        }

        // Only one thread should do deletes at a time, otherwise they'll conflict.
        boost::mutex::scoped_lock lock(_cappedDeleteMutex, boost::defer_lock);
        if (_cappedMaxDocs != -1) {
            lock.lock();
        } else {
            if (!lock.try_lock()) {
                // Someone else is deleting old records. Apply back-pressure if too far behind,
                // otherwise continue.
                if ((dataSize(txn) - _cappedMaxSize) < _cappedMaxSizeSlack)
                    return;

                lock.lock();

                // If we already waited, let someone else do cleanup unless we are significantly
                // over the limit.
                if ((dataSize(txn) - _cappedMaxSize) < (2 * _cappedMaxSizeSlack))
                    return;
            }
        }

        // we do this is a side transaction in case it aborts
        TempRecoveryUnitSwap swap(txn);

        int64_t ds = dataSize(txn);
        int64_t nr = numRecords(txn);
        int64_t sizeOverCap = (ds > _cappedMaxSize) ? ds - _cappedMaxSize : 0;
        int64_t sizeSaved = 0;
        int64_t docsOverCap = (_cappedMaxDocs != -1 && nr > _cappedMaxDocs) ? nr - _cappedMaxDocs : 0;
        int64_t docsRemoved = 0;

        try {
            WriteUnitOfWork wuow(txn);

            // We're going to notify the underlying store that we've
            // deleted this range of ids.  In TokuFT, this will trigger an
            // optimize.
            RecordId firstDeleted, lastDeleted;

            Timer t;

            // Delete documents while we are over-full and the iterator has more.
            //
            // Note that the iterator we get has the _idTracker's logic
            // already built in, so we don't need to worry about deleting
            // records that are not yet committed, including the one we
            // just inserted
            for (boost::scoped_ptr<RecordIterator> iter(getIterator(txn));
                 ((sizeSaved < sizeOverCap || docsRemoved < docsOverCap) &&
                  !iter->isEOF());
                 ) {
                const RecordId oldest = iter->getNext();

                ++docsRemoved;
                sizeSaved += iter->dataFor(oldest).size();

                if (_cappedDeleteCallback) {
                    // need to notify higher layers that a RecordId is about to be deleted
                    uassertStatusOK(_cappedDeleteCallback->aboutToDeleteCapped(txn, oldest, iter->dataFor(oldest)));
                }
                deleteRecord(txn, oldest);

                if (firstDeleted.isNull()) {
                    firstDeleted = oldest;
                }
                dassert(oldest > lastDeleted);
                lastDeleted = oldest;

                // Now, decide whether to keep working, we want to balance
                // staying on top of the deletion workload with the
                // latency of the client that's doing the deletes for
                // everyone.
                if (sizeOverCap >= _cappedMaxSizeSlack) {
                    // If we're over the slack amount, everyone's going to
                    // block on us anyway, so we may as well keep working.
                    continue;
                }
                if (sizeOverCap < (_cappedMaxSizeSlack / 4) && docsRemoved >= 1000) {
                    // If we aren't too much over and we've done a fair
                    // amount of work, take a break.
                    break;
                } else if (docsRemoved % 1000 == 0 && t.seconds() >= 4) {
                    // If we're under the slack amount and we've already
                    // spent a second working on this, return and give
                    // someone else a chance to shoulder that latency.
                    break;
                }
            }

            if (docsRemoved > 0) {
                _db->justDeletedCappedRange(txn, Slice::of(KeyString(firstDeleted)), Slice::of(KeyString(lastDeleted)),
                                            sizeSaved, docsRemoved);
                wuow.commit();
                dassert(lastDeleted > _lastDeletedId);
                _lastDeletedId = lastDeleted;
            }
        } catch (WriteConflictException) {
            log() << "Got conflict truncating capped, ignoring.";
            return;
        }
    }
Exemple #6
0
Param_t *GetParam(int argc, const char **argv)
/* 
!C******************************************************************************

!Description: 'GetParam' sets up the 'param' data structure and populate with user
 parameters, either from the command line or from a parameter file.
 
!Input Parameters:
 argc           number of command line arguments
 argv           command line argument list

!Output Parameters:
 (returns)      'param' data structure or NULL when an error occurs

!Team Unique Header:

 ! Design Notes:
   1. An error status is returned when:
       a. memory allocation is not successful
       b. an error is returned from the ReadCmdLine function
       c. certain required parameters are invalid or not entered:
            input file name, output file name, geolocation file name,
	    SDS name, output space projection number, 
	    output space pixel size, output space upper left corner, 
	    output space image size, either output space sphere or projection
	    parameter number 0
	    output space zone number not given for UTM
       d. the input is 'GRID_SPACE' then and certain required parameters 
          are invalid or not entered:
	    input space projection number, input space pixel size, 
	    input space upper left corner, either input space sphere or 
	    projection parameter number 0
       e. the input is 'GRID_SPACE' and the geolocation file name is given
       f. the resampling kernel is 'USER_KERNEL' and the kernel file name 
          is invalid or not entered.
   2. Error of type 'a' are handled with the 'RETURN_ERROR' macro and 
      the others are handled by writting the error messages to 'stderr' and 
      then printing the usage information.
   3. 'FreeParam' should be called to deallocate memory used by the 
      'param' data structures.

!END****************************************************************************
*/
{
  Param_t *this;
  char *error_string = (char *)NULL;
  FILE *fp;
  Key_t key;
  int i,len;
  char line[MAX_STR_LEN + 1];
  char temp[MAX_STR_LEN + 1];
  Param_key_t param_key;
  char *param_file_name;
  bool got_start, got_end;

  if (argc < 2) 
    RETURN_ERROR("no command line parameter", "GetParam", 
                 (Param_t *)NULL);
  if (argc > 2) 
    RETURN_ERROR("too many command line parameters", "GetParam", 
                 (Param_t *)NULL);
  if (strlen(argv[1]) < 1)
    RETURN_ERROR("no paramter file name", "GetParam", 
                 (Param_t *)NULL);
  param_file_name = (char *)argv[1];

  /* Open the parameter file */
  
  if ((fp = fopen(param_file_name, "r")) == (FILE *)NULL)
    RETURN_ERROR("unable to open parameter file", "GetParam", 
                 (Param_t *)NULL);

  /* Create the Param data structure */

  this = (Param_t *)malloc(sizeof(Param_t));
  if (this == (Param_t *)NULL) {
    fclose(fp);
    RETURN_ERROR("allocating Input structure", "GetParam", 
                 (Param_t *)NULL);
  }

  /* set default parameters */

  this->param_file_name  = (char *)NULL;
  this->input_file_name  = (char *)NULL;
  this->lut_file_name    = (char *)NULL;
  this->output_file_name = (char *)NULL;
  this->PGEVersion       = (char *)NULL;
  this->ProcessVersion   = (char *)NULL;
  this->num_ncep_files   = 0;            /* number of NCEP files     */
  this->num_prwv_files   = 0;            /* number of PRWV hdf files */
  this->num_ozon_files   = 0;            /* number of OZONe hdf files */
  this->dem_file = (char *)NULL;
  this->dem_flag = false;
  this->cloud_flag= false;
  this->thermal_band=false;

  /* Populate the data structure */

  this->param_file_name = DupString(param_file_name);
  if (this->param_file_name == (char *)NULL)
    error_string = "duplicating parameter file name";

  if (error_string == (char *)NULL) {
    this->lut_file_name = DupString(LUT_FILE_NAME);
    if (this->lut_file_name == (char *)NULL)
      error_string = "duplicating lookup table file name";
  }

  if (error_string != (char *)NULL) {
    if (this->param_file_name != (char *)NULL) 
      free(this->param_file_name);
    if (this->lut_file_name != (char *)NULL) 
      free(this->lut_file_name);
    FreeParam(this);
    RETURN_ERROR(error_string, "GetParam", (Param_t *)NULL);
  }

  /* Parse the header file */

  got_start = got_end = false;

  while((len = GetLine(fp, line)) > 0) {

    if (!StringParse(line, &key)) {
      sprintf(temp, "parsing header file; line = %s", line);
      error_string = temp;
      break;
    }
    if (key.len_key <= 0) continue;
    if (key.key[0] == '#') continue;

    param_key = (Param_key_t)
       KeyString(key.key, key.len_key, Param_string, 
		 (int)PARAM_NULL, (int)PARAM_MAX);
    if (param_key == PARAM_NULL) {
      key.key[key.len_key] = '\0';
      sprintf(temp, "invalid key; key = %s", key.key);
      error_string = temp;
      break;
    }
    if (!got_start) {
      if (param_key == PARAM_START) {
        if (key.nval != 0) {
	  error_string = "no value expected (start key)";
	  break;
	}
        got_start = true;
	continue;
      } else {
        error_string  = "no start key in parameter file";
        break;
      }
    }

    /* Get the value for each keyword */


    switch (param_key) {

      case PARAM_REF_FILE:
        if (key.nval <= 0) {
	  error_string = "no reflectance file name";
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many reflectance file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
	  error_string = "no reflectance file name";
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->input_file_name = DupString(key.value[0]);
	if (this->input_file_name == (char *)NULL) {
	  error_string = "duplicating reflectance file name";
	  break;
        }
        break;

      case PARAM_L5_REF:
        if (key.nval <= 0) {
          error_string = "no reflectance file name";
          break;
        } else if (key.nval > 1) {
          error_string = "too many reflectance file names";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no reflectance file name";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->input_file_name = DupString(key.value[0]);
        if (this->input_file_name == (char *)NULL) {
          error_string = "duplicating reflectance file name";
          break;
        }
        break;

      case PARAM_L7_REF:
        if (key.nval <= 0) {
          error_string = "no reflectance file name";
          break;
        } else if (key.nval > 1) {
          error_string = "too many reflectance file names";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no reflectance file name";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->input_file_name = DupString(key.value[0]);
        if (this->input_file_name == (char *)NULL) {
          error_string = "duplicating reflectance file name";
          break;
        }
        break;

      case PARAM_KTM_FILE:
        if (key.nval <= 0) {
          error_string = "no reflectance file name";
          break;
        } else if (key.nval > 1) {
          error_string = "too many reflectance file names";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no reflectance file name";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->input_file_name = DupString(key.value[0]);
        if (this->input_file_name == (char *)NULL) {
          error_string = "duplicating reflectance file name";
          break;
        }
        break;

      case PARAM_CSM_FILE:
        if (key.nval <= 0) {
          this->cloud_flag= false;
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many cloud mask file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
          this->cloud_flag= false;
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->cloud_mask_file  = DupString(key.value[0]);
	if (this->cloud_mask_file == (char *)NULL) {
	  error_string = "duplicating cloud mask file name";
	  break;
        }
		  this->cloud_flag= true;  /** NAZMI **/
		  printf("cloud mask set to true\n");
        break;

      case PARAM_L5_CSM:
        if (key.nval <= 0) {
          this->cloud_flag= false;
          break;
        } else if (key.nval > 1) {
          error_string = "too many cloud mask file names";
          break;
        }
        if (key.len_value[0] < 1) {
          this->cloud_flag= false;
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->cloud_mask_file  = DupString(key.value[0]);
        if (this->cloud_mask_file == (char *)NULL) {
          error_string = "duplicating cloud mask file name";
          break;
        }
                  this->cloud_flag= true;  /** NAZMI **/
        break;

      case PARAM_L7_CSM:
        if (key.nval <= 0) {
          this->cloud_flag= false;
          break;
        } else if (key.nval > 1) {
          error_string = "too many cloud mask file names";
          break;
        }
        if (key.len_value[0] < 1) {
          this->cloud_flag= false;
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->cloud_mask_file  = DupString(key.value[0]);
        if (this->cloud_mask_file == (char *)NULL) {
          error_string = "duplicating cloud mask file name";
          break;
        }
                  this->cloud_flag= true;  /** NAZMI **/
        break;

      case PARAM_TEMP_FILE:
        if (key.nval <= 0) {
		  this->thermal_band=false;
	  error_string = "no Temp file name";
	  break; 
	} else if (key.nval > 1) {
		  this->thermal_band=false;
	  error_string = "too many Temp file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
		  this->thermal_band=false;
	  error_string = "no Temp file name";
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
	this->thermal_band=true;
        this->temp_file_name = DupString(key.value[0]);
	if (this->temp_file_name == (char *)NULL) {
		  this->thermal_band=false;
	  error_string = "duplicating Temp file name";
	  break;
        }
        break;


      case PARAM_SR_FILE:
        if (key.nval <= 0) {
	  error_string = "no Kal/Thomas file name";
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many Kal/Thomas file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
	  error_string = "no Kal/Thomas file name";
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->output_file_name = DupString(key.value[0]);
	if (this->output_file_name == (char *)NULL) {
	  error_string = "duplicating Kal/Thomas file name";
	  break;
        }
        break;

      case PARAM_SR1_FILE:
        if (key.nval <= 0) {
          error_string = "no Kal/Thomas file name";
          break;
        } else if (key.nval > 1) {
          error_string = "too many Kal/Thomas file names";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no Kal/Thomas file name";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->output_file_name = DupString(key.value[0]);
        if (this->output_file_name == (char *)NULL) {
          error_string = "duplicating Kal/Thomas file name";
          break;
        }
        break;

      case PARAM_NCEP_FILE:
        this->num_ncep_files   = key.nval;            
	if (key.nval > 4) {
	  error_string = "too many NCEP file names";
	  break; 
	}
	for (i=0;i<key.nval;i++) {
		if (key.len_value[i] < 1) {
	 	 error_string = "no NCEP file name";
	 	 break;
		}
		key.value[i][key.len_value[i]] = '\0';
                this->ncep_file_name[i] = DupString(key.value[i]);
		if (this->ncep_file_name[i] == (char *)NULL) {
	  		error_string = "duplicating NCEP file name";
	 	   break;
                }
	}
        break;

      case PARAM_PRWV_FILE:
        this->num_prwv_files   = key.nval;       
	if (key.nval > 1) {
	  error_string = "too many PRWV file names";
	  break; 
	}
	if (key.nval > 0) {
		if (key.len_value[0] < 1) {
	 	 error_string = "no PRWV hdf file name";
	 	 break;
		}
		key.value[0][key.len_value[0]] = '\0';
                this->prwv_file_name = DupString(key.value[0]);
		if (this->prwv_file_name == (char *)NULL) {
                   error_string = "duplicating PRWV hdf file name";
	 	   break;
                }
	}
        break;

      case PARAM_PRW1_FILE:
        this->num_prwv_files   = key.nval;
        if (key.nval > 1) {
          error_string = "too many PRWV file names";
          break;
        }
        if (key.nval > 0) {
                if (key.len_value[0] < 1) {
                 error_string = "no PRWV hdf file name";
                 break;
                }
                key.value[0][key.len_value[0]] = '\0';
                this->prwv_file_name = DupString(key.value[0]);
                if (this->prwv_file_name == (char *)NULL) {
                   error_string = "duplicating PRWV hdf file name";
                   break;
                }
        }
        break;

      case PARAM_OZON_FILE:
        this->num_ozon_files   = key.nval;       
	if (key.nval > 1) {
	  error_string = "too many OZON file names";
	  break; 
	}
	if (key.nval > 0) {
		if (key.len_value[0] < 1) {
	 	 error_string = "no OZON hdf file name";
	 	 break;
		}
		key.value[0][key.len_value[0]] = '\0';
                this->ozon_file_name = DupString(key.value[0]);
		if (this->ozon_file_name == (char *)NULL) {
                   error_string = "duplicating OZON hdf file name";
	 	   break;
                }
	}
        break;

      case PARAM_OZO1_FILE:
        this->num_ozon_files   = key.nval;
        if (key.nval > 1) {
          error_string = "too many OZON file names";
          break;
        }
        if (key.nval > 0) {
                if (key.len_value[0] < 1) {
                 error_string = "no OZON hdf file name";
                 break;
                }
                key.value[0][key.len_value[0]] = '\0';
                this->ozon_file_name = DupString(key.value[0]);
                if (this->ozon_file_name == (char *)NULL) {
                   error_string = "duplicating OZON hdf file name";
                   break;
                }
        }
        break;

      case PARAM_DEM_FILE:
        this->dem_flag = true;
        if (key.nval <= 0) {
          this->dem_flag = false;
	  break; 
	} else if (key.nval > 1) {
	  error_string = "too many DEM file names";
	  break; 
	}
	if (key.len_value[0] < 1) {
          this->dem_flag = false;
	  break;
	}
	key.value[0][key.len_value[0]] = '\0';
        this->dem_file  = DupString(key.value[0]);
	if (this->dem_file == (char *)NULL) {
	  error_string = "duplicating dem file name";
	  break;
        }
        break;

      case PARAM_PGEVERSION:
        if (key.nval <= 0) {
          error_string = "no PGEVersion number";
          break;
        } else if (key.nval > 1) {
          error_string = "too many PGEVersion numbers";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no PGEVersion number";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->PGEVersion = DupString(key.value[0]);
        if (this->PGEVersion == (char *)NULL) {
          error_string = "duplicating PGEVersion number";
          break;
        }
        break;

      case PARAM_PROCESSVERSION:
        if (key.nval <= 0) {
          error_string = "no ProcessVersion number";
          break;
        } else if (key.nval > 1) {
          error_string = "too many ProcessVersion numbers";
          break;
        }
        if (key.len_value[0] < 1) {
          error_string = "no ProcessVersion number";
          break;
        }
        key.value[0][key.len_value[0]] = '\0';
        this->ProcessVersion = DupString(key.value[0]);
        if (this->ProcessVersion == (char *)NULL) {
          error_string = "duplicating ProcessVersion number";
          break;
        }
        break;

      case PARAM_END:
        if (key.nval != 0) {
	  error_string = "no value expected (end key)";
	  break; 
	}
        got_end = true;
        break;

      default:
        error_string = "key not implmented";

    }
    if (error_string != (char *)NULL) break;
    if (got_end) break;

  }

  /* Close the parameter file */

  fclose(fp);

  if (error_string == (char *)NULL) {
    if (!got_start) 
      error_string = "no start key in header";
    else if (!got_end)
      error_string = "no end key in header";
  }

  /* Handle null values */
  
  if (error_string == (char *)NULL) {
    if (this->input_file_name == (char *)NULL) 
      error_string = "no input file name given";
    if (this->lut_file_name == (char *)NULL) 
      error_string = "no lookup table file name given";
    if (this->output_file_name == (char *)NULL) 
      error_string = "no output file name given";
    if (this->PGEVersion == (char *)NULL)
      error_string = "no PGE Version given";
    if (this->ProcessVersion == (char *)NULL)
      error_string = "no Process Version given";
  }

  /* Handle errors */

  if (error_string != (char *)NULL) {
    if (this->param_file_name != (char *)NULL) 
      free(this->param_file_name);
    if (this->input_file_name != (char *)NULL) 
      free(this->input_file_name);
    if (this->lut_file_name != (char *)NULL) 
      free(this->lut_file_name);
    if (this->output_file_name != (char *)NULL) 
      free(this->output_file_name);
    if (this->PGEVersion != (char *)NULL)
      free(this->PGEVersion);
    if (this->ProcessVersion != (char *)NULL)
      free(this->ProcessVersion);
    if (this != (Param_t *)NULL) free(this);
    RETURN_ERROR(error_string, "GetParam", (Param_t *)NULL);
  }
  
  return this;
}