# bulkappend.sh - v1.0

# Directory Locations and other variable settings
ERRORS=0
LDAP_DIR=${ORACLE_HOME}/ldap
#LDAP_DIR=/vobs/ldap
LDAP_ADMIN=${LDAP_DIR}/admin
LDAP_BIN=${LDAP_DIR}/bin
LDAP_LOG=${LDAP_DIR}/log
LDAP_LOAD=${LDAP_DIR}/load
TMPDIR=${LDAP_DIR}/load
INSTALL_LOG=${LDAP_LOG}/bulkappend.log
SCHEMACHECK_LOG=${LDAP_LOG}/schemacheck.log
DATACHECK_LOG=${LDAP_LOG}/duplicateDN.log
LDAP_CONNECT=onldap
NEW_TREE=0
LOAD=0
GENERATE=0
PSWD="A"
ENCODING=".UTF8"
bo=``
no=``

# usage message
usage() {
  cat <<BULKAPP_SH_USAGE
usage: bulkappend.sh -connect <DB connect strings> [-generate] [-load] [-file <absolute path to LDIF data file> ]

   -connect  specifies the Net8 connect descriptors used to connect to 
             respective nodes.
   -generate Generate data files from the specified LDIF file. Perform schema 
             and duplicate dn checking against the first node specified.
   -load     Load data in the specified nodes
   -file     specify the LDIF file to be appended with absolute path.
   -encode   specifies the native character set (e.g ".ZHS16GBK" )

   At least one among -generate and -load should be specified.
   The pathname to the LDIF data file should be fully specified,
BULKAPP_SH_USAGE
  exit 2
}

usage_nofile() {
  cat << BULKAPP_SH_USAGE_NOFILE
No LDIF data file specified.

BULKAPP_SH_USAGE_NOFILE
}

usage_nocon() {
  cat <<BULKAPP_SH_USAGE_NOCON
Check Net8 client connect descriptor configuration settings.

BULKAPP_SH_USAGE_NOCON
}

createtblfile() {
      echo " set feedback off
             spool ${LDAP_LOG}/chktbl.lst
             DROP TABLE dn_check;
             CREATE TABLE dn_check (
                    NormDn     VARCHAR2(255) ,
                    DN   VARCHAR2(720))
             TABLESPACE OLTS_DEFAULT;
             INSERT INTO dn_check 
             ( Select parentdn||rdn , NULL
               from ct_dn
               where parentdn != ' ,'
               UNION
               Select rdn , NULL
               from ct_dn
               where parentdn = ' ,');
             COMMIT;
             spool off
             exit" > ${TMPDIR}/chktbl.sql

}
createchkfile() {
        echo " CREATE INDEX dn_check_ind ON dn_check(dn)
               UNRECOVERABLE PARALLEL 2
               TABLESPACE OLTS_DEFAULT;
               SET HEADING OFF
               SET TIMING OFF
               SET FEEDBACK OFF
               SET ECHO OFF
               SPOOL ${LDAP_LOG}/duplicateDN.log
               SELECT DN, NormDN
                FROM dn_check
                WHERE NormDN IN ( SELECT NormDN
                                   FROM dn_check
                                   GROUP BY NormDN
                                   HAVING COUNT(*) > 1)
		and dn IS NOT NULL
                ORDER BY 1, 2;
               SPOOL OFF;
               DROP INDEX dn_check_ind;
               DROP TABLE dn_check;
               COMMIT;
               EXIT; " > ${TMPDIR}/dupchk.sql
}

createctlfile() {
if [ ${attr} = "attr_store" ] ; then
COLUMN_STR="(ENTRYID \":ENTRYID + ${OFFSET}\",ATTRNAME,ATTRVAL,ATTRKIND,ATTRVER) "
elif [ ${attr} = "cn" ] ; then
COLUMN_STR="(ENTRYID \":ENTRYID + ${OFFSET}\",PARENTDN,ATTRVALUE )"
elif [ ${attr} = "dn" ] ; then
COLUMN_STR="(ENTRYID \":ENTRYID + ${OFFSET}\",RDN,PARENTDN )"
else
COLUMN_STR="(ENTRYID \":ENTRYID + ${OFFSET}\",ATTRVALUE )"
fi
if [ ${attr} = "attr_store" ] ; then
      echo " LOAD DATA
             INFILE '${attr}.dat'
             APPEND
             INTO TABLE ds_attrstore
             FIELDS TERMINATED BY X'ff'
             trailing nullcols
             ${COLUMN_STR} " > ${TMPDIR}/${attr}.ctl
else
      echo " LOAD DATA
             INFILE '${attr}.dat'
             APPEND
             INTO TABLE ct_${attr}
             FIELDS TERMINATED BY X'ff'
             trailing nullcols
             ${COLUMN_STR} " > ${TMPDIR}/${attr}.ctl
fi
}


modSequenceGenInNodes() {

  nosofentries=`wc -l ${LDAP_LOAD}/dn.dat | cut -f1 -d '/' `
   $ORACLE_HOME/bin/sqlplus ods/${PSWD}@${node} @${LDAP_ADMIN}/ldapbmsq.sql >>${INSTALL_LOG} 2>&1
  NEXTSEQVAL=`cat ${TMPDIR}/maxcatseq.val`
  OFFSET=`expr ${NEXTSEQVAL} - 100  `
  UPPER_LMT=`expr ${NEXTSEQVAL} + ${nosofentries} + 2000 `
  updateSequ
}
generatectlfiles() {
  ctllist=`ls *.dat`

  for ctlfile in $ctllist ; do
    attr=`echo ${ctlfile}|sed -e 's/.dat//'` ;
    createctlfile
  done
}
updateSequ() {
  for node in ${LDAP_CONNECT} ; do
  sed -e "s*%NEXTSEQVAL%*${UPPER_LMT}*g" ${LDAP_ADMIN}/ldapbnew.orc > ${TMPDIR}/newcatseq.sql
  $ORACLE_HOME/bin/sqlplus ods/${PSWD}@${node} @${TMPDIR}/newcatseq.sql >>${INSTALL_LOG} 2>&1
  rm -f ${TMPDIR}/newcatseq.sql > ${TMPDIR}/null
  done
}

schemaAndDupDNchecking() {

cd ${LDAP_LOAD}
    rm -f ${SCHEMACHECK_LOG} ${LDAP_LOG}/duplicateDN.log > ${TMPDIR}/null
   ${LDAP_BIN}/datagen connect=${MAIN_NODE} encode=${ENCODING} file=${BULKSRC} schemacheck=TRUE dnfile=${LDAP_LOAD}/dns.dat >${SCHEMACHECK_LOG} 2>&1
  if [ $? != 0 ] ; then
       ERRORS=1
       echo "datagen encountered errors in checking " ${BULKSRC}
       echo  " against node " ${MAIN_NODE}
       echo "see file " ${SCHEMACHECK_LOG}
       echo "Please correct the errors and restart this script."
       exit 1
  fi
  echo
  echo Schema Check Errors: ${SCHEMACHECK_LOG}
  echo
  if [ -s ${SCHEMACHECK_LOG} ] ; then
    cat ${SCHEMACHECK_LOG} 
    ERRORS=1
  else
    echo   None.
  fi

  createtblfile
  $ORACLE_HOME/bin/sqlplus ods/${PSWD}@${MAIN_NODE} @${TMPDIR}/chktbl.sql >>${INSTALL_LOG} 2>&1
  $ORACLE_HOME/bin/sqlldr ods/${PSWD}@${MAIN_NODE} control=${LDAP_LOAD}/dns.chk errors=10000 direct=false >>${INSTALL_LOG} 2>&1 
  createchkfile
  $ORACLE_HOME/bin/sqlplus ods/${PSWD}@${MAIN_NODE} @${TMPDIR}/dupchk.sql >>${INSTALL_LOG} 2>&1 
  echo
  echo Non-Unique Distinguished Names: ${LDAP_LOG}/duplicateDN.log
  echo
  if [ -s ${LDAP_LOG}/duplicateDN.log ] ; then
    cat ${LDAP_LOG}/duplicateDN.log
    ERRORS=1
  else
    echo   None.
  fi
rm -f ${TMPDIR}/chktbl.sql   ${TMPDIR}/dupchk.sql   > ${TMPDIR}/null
  echo
  echo -------------------------------------------------------------
  echo Bulkappend data verification complete
  echo -------------------------------------------------------------
  echo

# stop if errors encountered
if [ ${ERRORS} -ne 0 ] ; then
  exit 2;
fi

}



generateData() {

cd ${LDAP_LOAD}

${LDAP_BIN}/datagen connect=${MAIN_NODE} encode=${ENCODING} file=${BULKSRC} entrybase=2000 creatordn="cn\=bulkload" >>${INSTALL_LOG} 2>&1
  if [ $? != 0 ] ; then
      echo " Datageneration encounterd errors while processing" ${BULKSRD}
      echo " Please correct the errors and restart this script."
      exit 1
  fi

}

loadData() {
cd ${LDAP_LOAD}
  generatectlfiles

for NODE in ${LDAP_CONNECT} ; do

  echo 
  echo "   " ${NODE}
  echo
  #
  # Required Attribute Catalogs / Attribute Store
  #
  mainattrs=" attr_store  dn  cn  objectclass "
  for attr in ${mainattrs} ; do

  echo Loading ${attr} ..
  ${ORACLE_HOME}/bin/sqlldr userid=ods/${PSWD}@${NODE} control=${TMPDIR}/${attr}.ctl log=${LDAP_LOG}/${NODE}${attr}.log bad=${LDAP_LOG}/${NODE}${attr}.bad errors=10000000 direct=false 2>&1 >${TMPDIR}/null

  if [ -s ${LDAP_LOG}/${NODE}${attr}.bad ] ; then
     echo "       "Problems in loading in ct_${attr} table . See
     echo "       "${LDAP_LOG}/${NODE}${attr}.bad
  else
     rm -f ${LDAP_LOG}/${NODE}${attr}.* > ${TMPDIR}/null
  fi
  done

  #
  # Optional Search Catalogs
  #
  echo Loading Attribute Search Catalogs..

  # Generate list of sqlldr control files to load for attribute
  #  search catalogs
  ctllist=`ls *.dat`

  for ctlfile in $ctllist ; do
    # extract attribute name from control file name
    attr=`echo ${ctlfile}|sed -e 's/.dat//'` ;
    if [ -z "${attr}" -o ${attr} = "attr_store" -o ${attr} = "cn" -o ${attr} = "dn" -o ${attr} = "objectclass" -o ${attr} = "dns" ] ; then
      continue;
    fi
    echo "  " ${attr}..
    # generate/execute command
    ${ORACLE_HOME}/bin/sqlldr userid=ods/${PSWD}@${NODE} control=${TMPDIR}/${attr}.ctl log=${LDAP_LOG}/${NODE}${attr}.log bad=${LDAP_LOG}/${NODE}${attr}.bad errors=10000000 direct=false >${TMPDIR}/null 2>&1
  if [ -s ${LDAP_LOG}/${NODE}${attr}.bad ] ; then
     echo "       "Problems in loading in ct_${attr} table . See
     echo "       "${LDAP_LOG}/${NODE}${attr}.bad
  else
     rm -f ${LDAP_LOG}/${NODE}${attr}.* > ${TMPDIR}/null
  fi
  done

done

}
 
if [ $# -eq 0 ] ; then
 usage
fi
# parse arguments 
while [ $# -gt 0 ] ; do
  case $1 in
    -connect)  LDAP_CONNECT=" "$2 ; 
       if [ -z "${LDAP_CONNECT}" ] ; then
         usage ; 
       fi
       shift ;;
    -file) BULKSRC=$2;
        if [ -z "${BULKSRC}" ] ; then
           usage;
        fi
        shift;;
    -load) LOAD=1;;
    -generate) GENERATE=1;;
    -encode) ENCODING=$2;
             if [ -z "${ENCODING}" ] ; then
               ENCODING=".UTF8" ;
             fi;
             shift;;
    -w) PSWD=$2;
        shift;;
    *)  LDAP_CONNECT=${LDAP_CONNECT}" "$1 ;; 
  esac
  shift
done


# data file must be specified for generate option.
if [ ${GENERATE} -eq 0 -a ${LOAD} -eq 0 ] ; then
   echo Atleast one of the option -generate or -load should
   echo be specified.
   echo 
   usage
fi
if [ -z "${BULKSRC}" -a ${GENERATE} -eq 1 ] ; then
        usage_nofile
        usage
fi

# check for supporting SQL files
if [ ! -f ${LDAP_ADMIN}/ldapbnsq.sql ] ; then
        echo "Unable to locate required LDAP support files.  Check installation."
        exit 1
fi

# check for required envrionment variable settings
if [ -z "$ORACLE_HOME" ]
then
        echo "ORACLE_HOME must be set before running this script"
        exit 1
fi

echo
echo ${BASEDN}
echo

# check for connectivity to specified connect string
for nodes in ${LDAP_CONNECT} ; do 
  tnsping ${nodes} >${TMPDIR}/null 2>&1
  if [ $? != 0 ] ; then 
    echo Unable to detect database using connect descriptor -- ${nodes}
    ERRORS=1
  fi
done
# if there are errors in connecting to any of the nodes then exit.
if [ ${ERRORS} != 0 ] ; then
  usage_nocon
  usage
fi

####THis is the Security Implementation######
#### Please note that IF this tool is modified to support multiple nodes
### then do take care of security logic.. Currently it will work for only
## one node.
if [ ${PSWD} = "A" ] ; then
   echo " "
   echo "${bo}This tool can only be executed if you know database user password for OiD${no}"  
   echo " "
   printf "Enter OiD password ::" 
   stty -echo; read PSWD ; stty echo ; echo
   #clear
fi
for nodes in ${LDAP_CONNECT} ; do 
echo " set feedback off
   connect ods/${PSWD}@${nodes} ;
   exit; " > ${TMPDIR}/seccheck.sql
### check if the password provided is correct
${ORACLE_HOME}/bin/sqlplus  odscommon/odscommon@${nodes} @${TMPDIR}/seccheck.sql  > ${LDAP_LOG}/catchecK.lst
err=`grep -c ERROR ${LDAP_LOG}/catchecK.lst`
rm -f ${LDAP_LOG}/seccheck.lst ${TMPDIR}/seccheck.sql > ${TMPDIR}/null
if [ ${err} != 0 ] ; then
  echo " Password for OiD user is WRONG..for ${nodes}"
  echo " Cannot execute this tool ..."
  exit
fi
done

#############################

# After Checking that connection to all nodes is possible
## Set up the environment..
if [ ${GENERATE} -eq 1 ] ; then
  temp=0
  for node in ${LDAP_CONNECT} ; do
     if [ ${temp} = 0 ] ; then
        MAIN_NODE=${node}  
        schemaAndDupDNchecking
        generateData
     fi
     temp=1
  done
fi
if [ ${LOAD} -eq 1 ]; then
     modSequenceGenInNodes
     loadData
fi
