void RegThread::run() {
  DBG("registrar client started.\n");
  sleep(2); // wait for sems to completely start up

  while (true) {
    for (vector<RegInfo>::iterator it = registrations.begin(); 
	 it != registrations.end(); it++) {
      if (!check_registration(*it)) {
	DBG("Registration %d does not exist or timeout. Creating registration.\n",
	    (int)(it - registrations.begin()));
	create_registration(*it);
      }
    }
    sleep(10); // 10 seconds
  }
		
}
void pr_reserve_out(pr_context_t *context, lun_t lun,
                    const unsigned char *cdb, int session_id,
                    scsi_command_status_t *scsi_status)
{
    pr_info_t *pr_info = &context->pr_info[lun];

    EXA_ASSERT(session_id < MAX_GLOBAL_SESSION);

    if (cdb[0] == RESERVE_6)
    {
       if (persistent_spc2_reserve_lun(context, session_id, lun, scsi_status))
           SCSI_STATUS_OK(scsi_status, 0);
       else
           SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0);
       return;
    }

    if (cdb[0] == RELEASE_6)
    {
        if (persistent_spc2_release_lun(context, session_id, lun, scsi_status))
            SCSI_STATUS_OK(scsi_status, 0);
        else
            SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0);
        return;
    }

    if (cdb[0] == PERSISTENT_RESERVE_OUT)
    {
        /* int len = get_bigendian32(cdb + 5); // FIXME: TODO: must be checked for all service action */
        int pr_scope = cdb[2] >> 4;
        int pr_type = cdb[2] & 0xf;
        const unsigned char *param = cdb + SCSI_CDB_MAX_FIXED_LENGTH;

        pr_key_t reservation_key = get_bigendian64(param);
        pr_key_t service_action_key = get_bigendian64(param + 8);
        unsigned char flags = param[20];
        unsigned char spec_i_pt = (flags >> 3) & 1;
        /*    unsigned char all_tg_pt = (flags >>2) & 1 ; */
        int service_action = cdb[1] & 0x1f;

        /* spc3r23 table 116 "allowed scope" */
        if (pr_scope != PR_LU_SCOPE
            && service_action != PR_OUT_REGISTER
            && service_action != PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY
            && service_action != PR_OUT_CLEAR)
        {
            exalog_error("iSCSI PR failed: "
                         "reserve operation (%i) from session %i on LUN %" PRIlun
                         " is not allowed in this scope",
                         service_action, session_id, lun);
            SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION,
                              SCSI_SENSE_ILLEGAL_REQUEST,
                              SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB);
            return;
        }

        if (check_registration(context, session_id, lun, reservation_key,
                               service_action) != SCSI_STATUS_GOOD)
        {
            SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0);
            return;
        }

        switch (service_action)
        {
        case PR_OUT_REGISTER:
            if (spec_i_pt == 0)
            {
                persistent_register_lun(context, session_id,
                                        lun, service_action_key, scsi_status);
                break;
            }
            /* spec_i_pt == 1 ! */
            if (reservation_key != 0)   /* spec_i_pt == 1 and we are on a registered nexus */
            {
                exalog_warning("iSCSI PR conflict: "
                               "reserve operation (%i) from session %i on LUN %" PRIlun
                               " is not allowed, already registered nexus %" PRIu64,
                               service_action, session_id, lun, reservation_key);
                SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION,
                                  SCSI_SENSE_ILLEGAL_REQUEST,
                                  SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB);
                break;
                ;
            }

            persistent_register_lun(context, session_id, lun,
                                    service_action_key, scsi_status);
            break;

        case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
            if (service_action_key == 0
                && !pr_info_is_registered(pr_info, session_id))
            {
                /* FIXME: is this a "nothing to do" case ? */
                exalog_debug("iSCSI PR: register and ignore existing keys"
                             " from session %i on LUN %" PRIlun " (ntd)",
                             session_id, lun);

                SCSI_STATUS_OK(scsi_status, 0);
                break;
            }

            if (spec_i_pt == 1)
            {
                exalog_warning("iSCSI PR failed: "
                               "reserve operation (%i) from session %i on LUN %" PRIlun
                               " is not allowed",
                               service_action, session_id, lun);
                SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION,
                                  SCSI_SENSE_ILLEGAL_REQUEST,
                                  SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB);
                break;
            }
            persistent_register_lun(context, session_id, lun,
                                    service_action_key, scsi_status);
            break;

        case PR_OUT_RESERVE:
            if (persistent_reserve_lun(context, session_id, lun,
                                       reservation_key, pr_type))
                SCSI_STATUS_OK(scsi_status, 0);
            else
                SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT,
                                  0, 0);
            break;

        case PR_OUT_RELEASE:
            persistent_release_lun(context, session_id, lun,
                                   reservation_key, pr_type, scsi_status);
            break;

        case PR_OUT_CLEAR:
            persistent_clear_lun(context, session_id, lun, scsi_status);
            break;

        case PR_OUT_PREEMPT:
            persistent_preempt_lun(context, session_id, lun,
                                   reservation_key, service_action_key,
                                   pr_type, scsi_status);
            break;

        case PR_OUT_PREEMPT_AND_ABORT:
            persistent_preempt_lun(context, session_id, lun,
                                   reservation_key, service_action_key,
                                   pr_type, scsi_status);
            break;
            /* FIXME : we must add abort task set and it's not done spc3 - 5.6.10.5 */

        case PR_OUT_REGISTER_AND_MOVE:
            /* FIXME : not implemented ,not needed for windows */
            exalog_error("iSCSI PR failed: "
                         "reserve operation 'register_and_move' not supported"
                         " (from session %i on LUN %" PRIlun ")",
                         session_id, lun);
            SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION,
                              SCSI_SENSE_ILLEGAL_REQUEST, 0);
            break;

        default:
            exalog_error("iSCSI PR failed: "
                         "reserve operation (%i) not expected"
                         " (from session %i on LUN %" PRIlun ")",
                         service_action, session_id, lun);
            SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION,
                              SCSI_SENSE_ILLEGAL_REQUEST, 0);
            break;
        }

        /* PR generation sp3r23 6.11.2 */
        if (scsi_status->status == SCSI_STATUS_GOOD
            && service_action != PR_OUT_RESERVE
            && service_action != PR_OUT_RELEASE)
        {
            pr_info->pr_generation++;
        }
    }