Logo Search packages:      
Sourcecode: lfc version File versions  Download package

Cns_libpq_ifce.c

/*
 * Copyright (C) 2003-2009 by CERN/IT/DS/HSM
 * All rights reserved
 */
 
#ifndef lint
static char sccsid[] = "@(#)$RCSfile: Cns_libpq_ifce.c,v $ $Revision: 1.2 $ $Date: 2009/03/12 09:12:57 $ CERN IT-DS/HSM Jean-Philippe Baud";
#endif /* not lint */

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "Cns.h"
#include "Cns_server.h"
#include "Cthread_api.h"
#include "serrno.h"
#include "u64subr.h"

Cns_init_dbpkg()
{
      int i;

      return (0);
}

static void
Cns_libpq_error(func, sql_method, res, dbfd)
char *func;
char *sql_method;
PGresult *res;
struct Cns_dbfd *dbfd;
{
      extern char db_name[33];
      extern char db_pwd[33];
      extern char db_srvr[33];
      extern char db_user[33];
      ConnStatusType status = PQstatus (dbfd->Pconn);

      nslogit (func, "%s error: %s\n", sql_method, PQresultErrorMessage (res));
      PQclear (res);
      if (status == CONNECTION_BAD) {
            nslogit (func, "Trying to reconnect\n");
            Cns_closedb (dbfd);
            if (Cns_opendb (db_srvr, db_user, db_pwd, db_name, dbfd) < 0)
                  nslogit (func, "Reconnect failed\n");
      }
      serrno = SEINTERNAL;
}

Cns_abort_tr(dbfd)
struct Cns_dbfd *dbfd;
{
      PGresult *res;

      res = PQexec (dbfd->Pconn, "ROLLBACK");
      PQclear (res);    /* to avoid memory leaks */
      dbfd->tr_mode = 0;
      dbfd->tr_started = 0;
      return (0);
}

Cns_closedb(dbfd)
struct Cns_dbfd *dbfd;
{
      PQfinish (dbfd->Pconn);
      return (0);
}

Cns_decode_class_entry(res, row, lock, rec_addr, class_entry)
PGresult *res;
int row;
int lock;
Cns_dbrec_addr *rec_addr;
struct Cns_class_metadata *class_entry;
{
      int i = 0;

      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, row, i++));
      class_entry->classid = atoi (PQgetvalue (res, row, i++));
      strcpy (class_entry->name, PQgetvalue (res, row, i++));
      class_entry->uid = atoi (PQgetvalue (res, row, i++));
      class_entry->gid = atoi (PQgetvalue (res, row, i++));
      class_entry->min_filesize = atoi (PQgetvalue (res, row, i++));
      class_entry->max_filesize = atoi (PQgetvalue (res, row, i++));
      class_entry->flags = atoi (PQgetvalue (res, row, i++));
      class_entry->maxdrives = atoi (PQgetvalue (res, row, i++));
      class_entry->max_segsize = atoi (PQgetvalue (res, row, i++));
      class_entry->migr_time_interval = atoi (PQgetvalue (res, row, i++));
      class_entry->mintime_beforemigr = atoi (PQgetvalue (res, row, i++));
      class_entry->nbcopies = atoi (PQgetvalue (res, row, i++));
      class_entry->nbdirs_using_class = atoi (PQgetvalue (res, row, i++));
      class_entry->retenp_on_disk = atoi (PQgetvalue (res, row, i));
}

Cns_decode_fmd_entry(res, row, lock, rec_addr, fmd_entry)
PGresult *res;
int row;
int lock;
Cns_dbrec_addr *rec_addr;
struct Cns_file_metadata *fmd_entry;
{
      int i = 0;

      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, row, i++));
      fmd_entry->fileid = strtou64 (PQgetvalue (res, row, i++));
      fmd_entry->parent_fileid = strtou64 (PQgetvalue (res, row, i++));
      strcpy (fmd_entry->guid, PQgetvalue (res, row, i++));
      strcpy (fmd_entry->name, PQgetvalue (res, row, i++));
      fmd_entry->filemode = atoi (PQgetvalue (res, row, i++));
      fmd_entry->nlink = atoi (PQgetvalue (res, row, i++));
      fmd_entry->uid = atoi (PQgetvalue (res, row, i++));
      fmd_entry->gid = atoi (PQgetvalue (res, row, i++));
      fmd_entry->filesize = strtou64 (PQgetvalue (res, row, i++));
      fmd_entry->atime = atoi (PQgetvalue (res, row, i++));
      fmd_entry->mtime = atoi (PQgetvalue (res, row, i++));
      fmd_entry->ctime = atoi (PQgetvalue (res, row, i++));
      fmd_entry->fileclass = atoi (PQgetvalue (res, row, i++));
      fmd_entry->status = *(PQgetvalue (res, row, i++));
      strcpy (fmd_entry->csumtype, PQgetvalue (res, row, i++));
      strcpy (fmd_entry->csumvalue, PQgetvalue (res, row, i++));
      strcpy (fmd_entry->acl, PQgetvalue (res, row, i));
}

Cns_decode_rep_entry (res, row, lock, rec_addr, rep_entry)
PGresult *res;
int row;
int lock;
Cns_dbrec_addr *rec_addr;
struct Cns_file_replica *rep_entry;
{
      int i = 0;

      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, row, i++));
      rep_entry->fileid = strtou64 (PQgetvalue (res, row, i++));
      rep_entry->nbaccesses = strtou64 (PQgetvalue (res, row, i++));
      rep_entry->ctime = atoi (PQgetvalue (res, row, i++));
      rep_entry->atime = atoi (PQgetvalue (res, row, i++));
      rep_entry->ptime = atoi (PQgetvalue (res, row, i++));
      rep_entry->ltime = atoi (PQgetvalue (res, row, i++));
      rep_entry->r_type = *(PQgetvalue (res, row, i++));
      rep_entry->status = *(PQgetvalue (res, row, i++));
      rep_entry->f_type = *(PQgetvalue (res, row, i++));
      strcpy (rep_entry->setname, PQgetvalue (res, row, i++));
      strcpy (rep_entry->poolname, PQgetvalue (res, row, i++));
      strcpy (rep_entry->host, PQgetvalue (res, row, i++));
      strcpy (rep_entry->fs, PQgetvalue (res, row, i++));
      strcpy (rep_entry->sfn, PQgetvalue (res, row, i));
}

Cns_decode_smd_entry(res, row, lock, rec_addr, smd_entry)
PGresult *res;
int row;
int lock;
Cns_dbrec_addr *rec_addr;
struct Cns_seg_metadata *smd_entry;
{
      unsigned int blockid_tmp[4];
      int i = 0;

      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, row, i++));
      smd_entry->s_fileid = strtou64 (PQgetvalue (res, row, i++));
      smd_entry->copyno = atoi (PQgetvalue (res, row, i++));
      smd_entry->fsec = atoi (PQgetvalue (res, row, i++));
      smd_entry->segsize = strtou64 (PQgetvalue (res, row, i++));
      smd_entry->compression = atoi (PQgetvalue (res, row, i++));
      smd_entry->s_status = *(PQgetvalue (res, row, i++));
      strcpy (smd_entry->vid, PQgetvalue (res, row, i++));
      smd_entry->side = atoi (PQgetvalue (res, row, i++));
      smd_entry->fseq = atoi (PQgetvalue (res, row, i++));
      sscanf (PQgetvalue (res, row, i), "%02x%02x%02x%02x", &blockid_tmp[0],
          &blockid_tmp[1], &blockid_tmp[2], &blockid_tmp[3]);
      for (i = 0; i < 4; i++)
        smd_entry->blockid[i] = blockid_tmp[i];
}

Cns_decode_tppool_entry(res, row, lock, rec_addr, tppool_entry)
PGresult *res;
int row;
int lock;
Cns_dbrec_addr *rec_addr;
struct Cns_tp_pool *tppool_entry;
{
      int i = 0;

      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, row, i++));
      tppool_entry->classid = atoi (PQgetvalue (res, row, i++));
      strcpy (tppool_entry->tape_pool, PQgetvalue (res, row, i));
}

Cns_delete_class_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_class_metadata WHERE ROWID = %s";
      char func[23];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_class_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_fmd_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_file_metadata WHERE ROWID = %s";
      char func[21];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_fmd_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_lnk_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_symlinks WHERE ROWID = %s";
      char func[21];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_lnk_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_rep_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_file_replica WHERE ROWID = %s";
      char func[21];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_rep_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_smd_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_seg_metadata WHERE ROWID = %s";
      char func[21];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_smd_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_tppool_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_tp_pool WHERE ROWID = %s";
      char func[24];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_tppool_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_umd_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_user_metadata WHERE ROWID = %s";
      char func[21];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_umd_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "DELETE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_end_tr(dbfd)
struct Cns_dbfd *dbfd;
{
      PGresult *res;

      res = PQexec (dbfd->Pconn, "COMMIT");
      PQclear (res);    /* to avoid memory leaks */
      dbfd->tr_mode = 0;
      dbfd->tr_started = 0;
      return (0);
}

Cns_get_class_by_id(dbfd, classid, class_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
int classid;
struct Cns_class_metadata *class_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[20];
      static char query[] =
            "SELECT \
             CLASSID, NAME, OWNER_UID, GID, MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK \
            FROM Cns_class_metadata \
            WHERE classid = %d";
      static char query4upd[] =
            "SELECT ROWID, \
             CLASSID, NAME, OWNER_UID, GID, MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK \
            FROM Cns_class_metadata \
            WHERE classid = %d \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_class_by_id");
      sprintf (sql_stmt, lock ? query4upd : query, classid);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_class_entry (res, 0, lock, rec_addr, class_entry);
      PQclear (res);
      return (0);
}

Cns_get_class_by_name(dbfd, class_name, class_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
char *class_name;
struct Cns_class_metadata *class_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[22];
      static char query[] =
            "SELECT \
             CLASSID, NAME, OWNER_UID, GID, MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK \
            FROM Cns_class_metadata \
            WHERE name = '%s'";
      static char query4upd[] =
            "SELECT ROWID, \
             CLASSID, NAME, OWNER_UID, GID, MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK \
            FROM Cns_class_metadata \
            WHERE name = '%s' \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_class_by_name");
      sprintf (sql_stmt, lock ? query4upd : query, class_name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_class_entry (res, 0, lock, rec_addr, class_entry);
      PQclear (res);
      return (0);
}

Cns_get_fmd_by_fileid(dbfd, fileid, fmd_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
u_signed64 fileid;
struct Cns_file_metadata *fmd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char fileid_str[21];
      char func[22];
      static char query[] =
            "SELECT \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE fileid = %s";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE fileid = %s \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_fmd_by_fileid");
      sprintf (sql_stmt, lock ? query4upd : query,
          u64tostr (fileid, fileid_str, -1));
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_fmd_entry (res, 0, lock, rec_addr, fmd_entry);
      PQclear (res);
      return (0);
}

Cns_get_fmd_by_fullid(dbfd, parent_fileid, name, fmd_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
u_signed64 parent_fileid;
char *name;
struct Cns_file_metadata *fmd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char escaped_name[CA_MAXNAMELEN*2+1];
      char func[22];
      char parent_fileid_str[21];
      static char query[] =
            "SELECT \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE parent_fileid = %s \
            AND name = '%s'";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE parent_fileid = %s \
            AND name = '%s' \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_fmd_by_fullid");
      PQescapeStringConn (dbfd->Pconn, escaped_name, name, strlen (name), NULL);
      sprintf (sql_stmt, lock ? query4upd : query,
          u64tostr (parent_fileid, parent_fileid_str, 0), escaped_name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_fmd_entry (res, 0, lock, rec_addr, fmd_entry);
      PQclear (res);
      return (0);
}

Cns_get_fmd_by_guid(dbfd, guid, fmd_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
char *guid;
struct Cns_file_metadata *fmd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[20];
      static char query[] =
            "SELECT \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE guid = '%s'";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE guid = '%s' \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_fmd_by_guid");
      sprintf (sql_stmt, lock ? query4upd : query, guid);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_fmd_entry (res, 0, lock, rec_addr, fmd_entry);
      PQclear (res);
      return (0);
}

Cns_get_fmd_by_pfid(dbfd, bod, parent_fileid, pattern, fmd_entry, getattr, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bod;
u_signed64 parent_fileid;
char *pattern;
struct Cns_file_metadata *fmd_entry;
int getattr;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[20];
      char parent_fileid_str[21];
      static char query[] =
            "SELECT \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE parent_fileid = %s \
            ORDER BY name";
      static char query_name[] =
            "SELECT \
             NAME \
            FROM Cns_file_metadata \
            WHERE parent_fileid = %s \
            ORDER BY name";
      static char query_pattern[] =
            "SELECT \
             FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL \
            FROM Cns_file_metadata \
            WHERE parent_fileid = %s AND name LIKE '%s' \
            ORDER BY name";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_fmd_by_pfid");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bod) {
            if (*pattern)
                  sprintf (sql_stmt, query_pattern,
                      u64tostr (parent_fileid, parent_fileid_str, -1), pattern);
            else
                  sprintf (sql_stmt, getattr ? query : query_name,
                      u64tostr (parent_fileid, parent_fileid_str, -1));
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      if (! getattr)
            strcpy (fmd_entry->name, PQgetvalue (dblistptr->res,
                dblistptr->row, 0));
      else
            Cns_decode_fmd_entry (dblistptr->res, dblistptr->row, 0, NULL,
                fmd_entry);
      dblistptr->row++;
      return (0);
}

Cns_get_lnk_by_fileid(dbfd, fileid, lnk_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
u_signed64 fileid;
struct Cns_symlinks *lnk_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char fileid_str[21];
      char func[22];
      static char query[] =
            "SELECT \
             FILEID, LINKNAME \
            FROM Cns_symlinks \
            WHERE fileid = %s";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, LINKNAME \
            FROM Cns_symlinks \
            WHERE fileid = %s \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_lnk_by_fileid");
      sprintf (sql_stmt, lock ? query4upd : query,
          u64tostr (fileid, fileid_str, -1));
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, 0));
      lnk_entry->fileid = fileid;
      strcpy (lnk_entry->linkname, PQgetvalue (res, 0, lock ? 2 : 1));
      PQclear (res);
      return (0);
}

Cns_get_max_copyno (dbfd, fileid, copyno)
struct Cns_dbfd *dbfd;
u_signed64 fileid;
int *copyno;
{
      char fileid_str[21];
      char func[19];
      static char query[] =
            "SELECT COPYNO \
            FROM Cns_seg_metadata \
            WHERE s_fileid = %s \
            ORDER BY copyno DESC LIMIT 1";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_max_copyno");
      sprintf (sql_stmt, query, u64tostr (fileid, fileid_str, -1));
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      *copyno = atoi (PQgetvalue (res, 0, 0));
      PQclear (res);
      return (0);
}

Cns_get_rep_by_sfn(dbfd, sfn, rep_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
char *sfn;
struct Cns_file_replica *rep_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char escaped_name[CA_MAXSFNLEN*2+1];
      char func[19];
      static char query[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE sfn = '%s'";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE sfn = '%s' \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[2385];

      strcpy (func, "Cns_get_rep_by_sfn");
      PQescapeStringConn (dbfd->Pconn, escaped_name, sfn, strlen (sfn), NULL);
      sprintf (sql_stmt, lock ? query4upd : query, escaped_name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_rep_entry (res, 0, lock, rec_addr, rep_entry);
      PQclear (res);
      return (0);
}

Cns_get_smd_by_fullid(dbfd, fileid, copyno, fsec, smd_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
u_signed64 fileid;
int copyno;
int fsec;
struct Cns_seg_metadata *smd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char fileid_str[21];
      char func[22];
      static char query[] =
            "SELECT \
             S_FILEID, COPYNO, FSEC, SEGSIZE, COALESCE(COMPRESSION,100), \
             S_STATUS, VID, SIDE, FSEQ, BLOCKID \
            FROM Cns_seg_metadata \
            WHERE s_fileid = %s \
            AND copyno = %d AND fsec = %d";
      static char query4upd[] =
            "SELECT ROWID, \
             S_FILEID, COPYNO, FSEC, SEGSIZE, COALESCE(COMPRESSION,100), \
             S_STATUS, VID, SIDE, FSEQ, BLOCKID \
            FROM Cns_seg_metadata \
            WHERE s_fileid = %s \
            AND copyno = %d AND fsec = %d \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_smd_by_fullid");
      sprintf (sql_stmt, lock ? query4upd : query,
          u64tostr (fileid, fileid_str, -1), copyno, fsec);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      Cns_decode_smd_entry (res, 0, lock, rec_addr, smd_entry);
      PQclear (res);
      return (0);
}

Cns_get_smd_by_pfid(dbfd, bof, fileid, smd_entry, lock, rec_addr, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bof;
u_signed64 fileid;
struct Cns_seg_metadata *smd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
int endlist;
DBLISTPTR *dblistptr;
{
      char fileid_str[21];
      char func[20];
      static char query[] =
            "SELECT \
             S_FILEID, COPYNO, FSEC, SEGSIZE, COALESCE(COMPRESSION,100), \
             S_STATUS, VID, SIDE, FSEQ, BLOCKID \
            FROM Cns_seg_metadata \
            WHERE s_fileid = %s \
            ORDER BY copyno, fsec";
      static char query4upd[] =
            "SELECT ROWID, \
             S_FILEID, COPYNO, FSEC, SEGSIZE, COALESCE(COMPRESSION,100), \
             S_STATUS, VID, SIDE, FSEQ, BLOCKID \
            FROM Cns_seg_metadata \
            WHERE s_fileid = %s \
            ORDER BY copyno, fsec \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_smd_by_pfid");
      if (endlist) {
            if (dblistptr->res) {
                  PQclear (dblistptr->res);
                  dblistptr->res = NULL;
            }
            return (1);
      }
      if (bof) {
            sprintf (sql_stmt, lock ? query4upd : query,
                u64tostr (fileid, fileid_str, -1));
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_smd_entry (dblistptr->res, dblistptr->row, lock, rec_addr,
          smd_entry);
      dblistptr->row++;
      return (0);
}

Cns_get_smd_by_vid(dbfd, bov, vid, smd_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bov;
char *vid;
struct Cns_seg_metadata *smd_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[19];
      static char query[] =
            "SELECT \
             S_FILEID, COPYNO, FSEC, SEGSIZE, COALESCE(COMPRESSION,100), \
             S_STATUS, VID, SIDE, FSEQ, BLOCKID \
            FROM Cns_seg_metadata \
            WHERE vid = '%s' \
            ORDER BY side, fseq";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_smd_by_vid");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bov) {
            sprintf (sql_stmt, query, vid);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_smd_entry (dblistptr->res, dblistptr->row, 0, NULL, smd_entry);
      dblistptr->row++;
      return (0);
}

Cns_get_tppool_by_cid(dbfd, bol, classid, tppool_entry, lock, rec_addr, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
int classid;
struct Cns_tp_pool *tppool_entry;
int lock;
Cns_dbrec_addr *rec_addr;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[22];
      static char query[] =
            "SELECT \
             CLASSID, TAPE_POOL \
            FROM Cns_tp_pool \
            WHERE classid = %d";
      static char query4upd[] =
            "SELECT ROWID, \
             CLASSID, TAPE_POOL \
            FROM Cns_tp_pool \
            WHERE classid = %d \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_tppool_by_cid");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            sprintf (sql_stmt, lock ? query4upd : query, classid);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_tppool_entry (dblistptr->res, dblistptr->row, lock, rec_addr,
          tppool_entry);
      dblistptr->row++;
      return (0);
}

Cns_get_umd_by_fileid(dbfd, fileid, umd_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
u_signed64 fileid;
struct Cns_user_metadata *umd_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char fileid_str[21];
      char func[22];
      static char query[] =
            "SELECT \
             U_FILEID, COMMENTS \
            FROM Cns_user_metadata \
            WHERE u_fileid = %s";
      static char query4upd[] =
            "SELECT ROWID, \
             U_FILEID, COMMENTS \
            FROM Cns_user_metadata \
            WHERE u_fileid = %s \
            FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_umd_by_fileid");
      sprintf (sql_stmt, lock ? query4upd : query,
          u64tostr (fileid, fileid_str, -1));
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, 0));
      umd_entry->u_fileid = fileid;
      strcpy (umd_entry->comments, PQgetvalue (res, 0, lock ? 2 : 1));
      PQclear (res);
      return (0);
}

Cns_insert_class_entry(dbfd, class_entry)
struct Cns_dbfd *dbfd;
struct Cns_class_metadata *class_entry;
{
      char func[23];
      static char insert_stmt[] =
            "INSERT INTO Cns_class_metadata \
            (CLASSID, NAME, OWNER_UID, GID, MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK) \
            VALUES \
            (%d, '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_class_entry");
      sprintf (sql_stmt, insert_stmt,
          class_entry->classid, class_entry->name,
          class_entry->uid, class_entry->gid,
          class_entry->min_filesize, class_entry->max_filesize,
          class_entry->flags, class_entry->maxdrives,
          class_entry->max_segsize, class_entry->migr_time_interval,
          class_entry->mintime_beforemigr, class_entry->nbcopies,
          class_entry->nbdirs_using_class, class_entry->retenp_on_disk);
      
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_fmd_entry(dbfd, fmd_entry)
struct Cns_dbfd *dbfd;
struct Cns_file_metadata *fmd_entry;
{
      char escaped_name[CA_MAXNAMELEN*2+1];
      char fileid_str[21];
      char filesize_str[21];
      char func[21];
      static char insert_stmt[] =
            "INSERT INTO Cns_file_metadata \
            (FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL) \
            VALUES \
            (%s, %s, '%s', '%s', %d, %d, %d, %d, %s, %d, %d, %d, %d, '%c', '%s', '%s', '%s')";
      static char insert_stmt_null_guid[] =
            "INSERT INTO Cns_file_metadata \
            (FILEID, PARENT_FILEID, GUID, NAME, FILEMODE, NLINK, OWNER_UID, \
             GID, FILESIZE, ATIME, MTIME, CTIME, FILECLASS, STATUS, CSUMTYPE, \
             CSUMVALUE, ACL) \
            VALUES \
            (%s, %s, NULL, '%s', %d, %d, %d, %d, %s, %d, %d, %d, %d, '%c', '%s', '%s', '%s')";
      char parent_fileid_str[21];
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_fmd_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, fmd_entry->name,
          strlen (fmd_entry->name), NULL);
      if (*fmd_entry->guid)
            sprintf (sql_stmt, insert_stmt,
                u64tostr (fmd_entry->fileid, fileid_str, -1),
                u64tostr (fmd_entry->parent_fileid, parent_fileid_str, -1),
                fmd_entry->guid, escaped_name, fmd_entry->filemode, fmd_entry->nlink,
                fmd_entry->uid, fmd_entry->gid,
                u64tostr (fmd_entry->filesize, filesize_str, -1),
                (int)fmd_entry->atime, (int)fmd_entry->mtime, (int)fmd_entry->ctime,
                fmd_entry->fileclass, fmd_entry->status, fmd_entry->csumtype,
                fmd_entry->csumvalue, fmd_entry->acl);
      else  /* must insert a NULL guid and not an empty string because of
               the UNIQUE constraint on guid */
            sprintf (sql_stmt, insert_stmt_null_guid,
                u64tostr (fmd_entry->fileid, fileid_str, -1),
                u64tostr (fmd_entry->parent_fileid, parent_fileid_str, -1),
                escaped_name, fmd_entry->filemode, fmd_entry->nlink,
                fmd_entry->uid, fmd_entry->gid,
                u64tostr (fmd_entry->filesize, filesize_str, -1),
                (int)fmd_entry->atime, (int)fmd_entry->mtime, (int)fmd_entry->ctime,
                fmd_entry->fileclass, fmd_entry->status, fmd_entry->csumtype,
                fmd_entry->csumvalue, fmd_entry->acl);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_lnk_entry(dbfd, lnk_entry)
struct Cns_dbfd *dbfd;
struct Cns_symlinks *lnk_entry;
{
      char escaped_name[CA_MAXPATHLEN*2+1];
      char fileid_str[21];
      char func[21];
      static char insert_stmt[] =
            "INSERT INTO Cns_symlinks \
            (FILEID, LINKNAME) \
            VALUES \
            (%s, '%s')";
      PGresult *res;
      char sql_stmt[2130];

      strcpy (func, "Cns_insert_lnk_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, lnk_entry->linkname,
          strlen (lnk_entry->linkname), NULL);
      sprintf (sql_stmt, insert_stmt,
          u64tostr (lnk_entry->fileid, fileid_str, -1), escaped_name);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_rep_entry(dbfd, rep_entry)
struct Cns_dbfd *dbfd;
struct Cns_file_replica *rep_entry;
{
      char escaped_name[CA_MAXSFNLEN*2+1];
      char fileid_str[21];
      char func[21];
      static char insert_stmt[] =
            "INSERT INTO Cns_file_replica \
            (FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN) \
            VALUES \
            (%s, %s, %d, %d, %d, %d, '%c', '%c', '%c', '%s', '%s', '%s', '%s', '%s')";
      static char insert_stmt_null_ftype[] =
            "INSERT INTO Cns_file_replica \
            (FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN) \
            VALUES \
            (%s, %s, %d, %d, %d, %d, '%c', '%c', NULL, '%s', '%s', '%s', '%s', '%s')";
      static char insert_stmt_null_rtype[] =
            "INSERT INTO Cns_file_replica \
            (FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN) \
            VALUES \
            (%s, %s, %d, %d, %d, %d, NULL, '%c', '%c', '%s', '%s', '%s', '%s', '%s')";
      static char insert_stmt_null_types[] =
            "INSERT INTO Cns_file_replica \
            (FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN) \
            VALUES \
            (%s, %s, %d, %d, %d, %d, NULL, '%c', NULL, '%s', '%s', '%s', '%s', '%s')";
      char nbacces_str[21];
      static char query_stmt[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE sfn = '%s'";
      PGresult *res;
      char sql_stmt[2681];

      strcpy (func, "Cns_insert_rep_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, rep_entry->sfn,
          strlen (rep_entry->sfn), NULL);

      if (rep_entry->f_type) {
            if (rep_entry->r_type)
                  sprintf (sql_stmt, insert_stmt,
                      u64tostr (rep_entry->fileid, fileid_str, -1),
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->r_type, rep_entry->status,
                      rep_entry->f_type, rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name);
            else
                  sprintf (sql_stmt, insert_stmt_null_rtype,
                      u64tostr (rep_entry->fileid, fileid_str, -1),
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->status, rep_entry->f_type,
                      rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name);
      } else {
            if (rep_entry->r_type)
                  sprintf (sql_stmt, insert_stmt_null_ftype,
                      u64tostr (rep_entry->fileid, fileid_str, -1),
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->r_type, rep_entry->status,
                      rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name);
            else
                  sprintf (sql_stmt, insert_stmt_null_types,
                      u64tostr (rep_entry->fileid, fileid_str, -1),
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->status,
                      rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name);
      }

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_smd_entry(dbfd, smd_entry)
struct Cns_dbfd *dbfd;
struct Cns_seg_metadata *smd_entry;
{
      char fileid_str[21];
      char func[21];
      static char insert_stmt[] =
            "INSERT INTO Cns_seg_metadata \
            (S_FILEID, COPYNO, FSEC, \
             SEGSIZE, COMPRESSION, S_STATUS, \
             VID, SIDE, FSEQ, BLOCKID) \
            VALUES \
            (%s, %d, %d, %s, %d, '%c', '%s', %d, %d, '%02x%02x%02x%02x')";
      PGresult *res;
      char segsize_str[21];
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_smd_entry");
      sprintf (sql_stmt, insert_stmt,
          u64tostr (smd_entry->s_fileid, fileid_str, -1),
          smd_entry->copyno, smd_entry->fsec,
          u64tostr (smd_entry->segsize, segsize_str, -1),
          smd_entry->compression, smd_entry->s_status,
          smd_entry->vid, smd_entry->side, smd_entry->fseq,
          smd_entry->blockid[0], smd_entry->blockid[1],
          smd_entry->blockid[2], smd_entry->blockid[3]);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_tppool_entry(dbfd, tppool_entry)
struct Cns_dbfd *dbfd;
struct Cns_tp_pool *tppool_entry;
{
      char func[24];
      static char insert_stmt[] =
            "INSERT INTO Cns_tp_pool \
            (CLASSID, TAPE_POOL) \
            VALUES \
            (%d, '%s')";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_tppool_entry");
      sprintf (sql_stmt, insert_stmt,
          tppool_entry->classid, tppool_entry->tape_pool);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_umd_entry(dbfd, umd_entry)
struct Cns_dbfd *dbfd;
struct Cns_user_metadata *umd_entry;
{
      char fileid_str[21];
      char func[21];
      static char insert_stmt[] =
            "INSERT INTO Cns_user_metadata \
            (U_FILEID, COMMENTS) \
            VALUES \
            (%s, '%s')";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_umd_entry");
      sprintf (sql_stmt, insert_stmt,
          u64tostr (umd_entry->u_fileid, fileid_str, -1),
          umd_entry->comments);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_list_class_entry(dbfd, bol, class_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
struct Cns_class_metadata *class_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[21];
      static char query[] =
            "SELECT \
             CLASSID, NAME, \
             OWNER_UID, GID, \
             MIN_FILESIZE, MAX_FILESIZE, \
             FLAGS, MAXDRIVES, \
             MAX_SEGSIZE, MIGR_TIME_INTERVAL, \
             MINTIME_BEFOREMIGR, NBCOPIES, \
             NBDIRS_USING_CLASS, RETENP_ON_DISK \
            FROM Cns_class_metadata \
            ORDER BY classid";
      PGresult *res;

      strcpy (func, "Cns_list_class_entry");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            res = PQexec (dbfd->Pconn, query);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_class_entry (dblistptr->res, dblistptr->row, 0, NULL,
          class_entry);
      dblistptr->row++;
      return (0);
}

Cns_list_group_entry(dbfd, bol, group_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
struct Cns_groupinfo *group_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[21];
      static char query[] =
            "SELECT \
             GID, GROUPNAME \
            FROM Cns_groupinfo \
            ORDER BY gid";
      PGresult *res;

      strcpy (func, "Cns_list_group_entry");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            res = PQexec (dbfd->Pconn, query);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      group_entry->gid = atoi (PQgetvalue (dblistptr->res, dblistptr->row, 0));
      strcpy (group_entry->groupname, PQgetvalue (dblistptr->res, dblistptr->row, 1));
      dblistptr->row++;
      return (0);
}

Cns_list_lnk_entry(dbfd, bol, linkname, lnk_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
char *linkname;
struct Cns_symlinks *lnk_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char escaped_name[CA_MAXPATHLEN*2+1];
      char fileid_str[21];
      char func[19];
      static char query[] =
            "SELECT \
             FILEID, LINKNAME \
            FROM Cns_symlinks \
            WHERE linkname = '%s'";
      PGresult *res;
      char sql_stmt[2115];

      strcpy (func, "Cns_list_lnk_entry");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            PQescapeStringConn (dbfd->Pconn, escaped_name, linkname,
                strlen (linkname), NULL);
            sprintf (sql_stmt, query, escaped_name);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      lnk_entry->fileid = strtou64 (PQgetvalue (dblistptr->res, dblistptr->row, 0));
      strcpy (lnk_entry->linkname, PQgetvalue (dblistptr->res, dblistptr->row, 1));
      dblistptr->row++;
      return (0);
}

Cns_list_rep4admin(dbfd, bol, poolname, server, fs, rep_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
char *poolname;
char *server;
char *fs;
struct Cns_file_replica *rep_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[19];
      static char queryf[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE host = '%s' AND fs = '%s'";
      static char queryp[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE poolname = '%s'";
      static char queryps[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE poolname = '%s' AND host = '%s'";
      static char querys[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE host = '%s'";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_list_rep4admin");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            if (*fs)
                  sprintf (sql_stmt, queryf, server, fs);
            else if (! *poolname)
                  sprintf (sql_stmt, querys, server);
            else if (*server)
                  sprintf (sql_stmt, queryps, poolname, server);
            else
                  sprintf (sql_stmt, queryp, poolname);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_rep_entry (dblistptr->res, dblistptr->row, 0, NULL, rep_entry);
      dblistptr->row++;
      return (0);
}

Cns_list_rep4gc(dbfd, bol, poolname, rep_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
char *poolname;
struct Cns_file_replica *rep_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[16];
      static char query[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE poolname = '%s' AND status = '-' AND ltime < %d \
            ORDER BY atime";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_list_rep4gc");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            sprintf (sql_stmt, query, poolname, time (0));
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_rep_entry (dblistptr->res, dblistptr->row, 0, NULL, rep_entry);
      dblistptr->row++;
      return (0);
}

Cns_list_rep_entry(dbfd, bol, fileid, rep_entry, lock, rec_addr, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
u_signed64 fileid;
struct Cns_file_replica *rep_entry;
int lock;
Cns_dbrec_addr *rec_addr;
int endlist;
DBLISTPTR *dblistptr;
{
      char fileid_str[21];
      char func[19];
      static char query[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE fileid = %s \
            ORDER BY sfn";
      static char query4upd[] =
            "SELECT ROWID, \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE fileid = %s \
            ORDER BY sfn";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_list_rep_entry");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            sprintf (sql_stmt, lock ? query4upd : query,
                u64tostr (fileid, fileid_str, -1));
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_rep_entry (dblistptr->res, dblistptr->row, lock, rec_addr, rep_entry);
      dblistptr->row++;
      return (0);
}

Cns_list_rep_set(dbfd, bol, setname, rep_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
char *setname;
struct Cns_file_replica *rep_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[17];
      static char query[] =
            "SELECT \
             FILEID, NBACCESSES, CTIME, ATIME, PTIME, LTIME, R_TYPE, \
             STATUS, F_TYPE, SETNAME, POOLNAME, HOST, FS, SFN \
            FROM Cns_file_replica \
            WHERE setname = '%s'";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_list_rep_set");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            sprintf (sql_stmt, query, setname);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      Cns_decode_rep_entry (dblistptr->res, dblistptr->row, 0, NULL, rep_entry);
      dblistptr->row++;
      return (0);
}

Cns_list_user_entry(dbfd, bol, user_entry, endlist, dblistptr)
struct Cns_dbfd *dbfd;
int bol;
struct Cns_userinfo *user_entry;
int endlist;
DBLISTPTR *dblistptr;
{
      char func[20];
      static char query[] =
            "SELECT \
             USERID, USERNAME \
            FROM Cns_userinfo \
            ORDER BY userid";
      PGresult *res;

      strcpy (func, "Cns_list_user_entry");
      if (endlist) {
            PQclear (dblistptr->res);
            return (1);
      }
      if (bol) {
            res = PQexec (dbfd->Pconn, query);
            if (PQresultStatus (res) != PGRES_TUPLES_OK) {
                  Cns_libpq_error (func, "SELECT", res, dbfd);
                  return (-1);
            }
            dblistptr->res = res;
            dblistptr->row = 0;
      }
      if (dblistptr->row >= PQntuples (dblistptr->res))
            return (1);
      user_entry->userid = atoi (PQgetvalue (dblistptr->res, dblistptr->row, 0));
      strcpy (user_entry->username, PQgetvalue (dblistptr->res, dblistptr->row, 1));
      dblistptr->row++;
      return (0);
}

Cns_opendb(db_srvr, db_user, db_pwd, db_name, dbfd)
char *db_srvr;
char *db_user;
char *db_pwd;
char *db_name;
struct Cns_dbfd *dbfd;
{
      char connectstr[256];
      char func[16];
      int ntries;

      strcpy (func, "Cns_opendb");
      sprintf (connectstr, "dbname=%s user=%s password=%s", db_name, db_user, db_pwd);
      ntries = 0;
      while (1) {
            dbfd->Pconn = PQconnectdb (connectstr);
            if (PQstatus (dbfd->Pconn) == CONNECTION_OK) return (0);
            if (ntries++ >= MAXRETRY) break;
            sleep (RETRYI);
      }
      nslogit (func, "CONNECT error: %s\n", PQerrorMessage (dbfd->Pconn));
      serrno = SEINTERNAL;
      return (-1);
}

Cns_start_tr(s, dbfd)
int s;
struct Cns_dbfd *dbfd;
{
      PGresult *res;

      if (! dbfd->tr_started) {
            res = PQexec (dbfd->Pconn, "BEGIN");
            PQclear (res);    /* to avoid memory leaks */
            dbfd->tr_started = 1;
      }
      return (0);
}

Cns_unique_id(dbfd, unique_id)
struct Cns_dbfd *dbfd;
u_signed64 *unique_id;
{
      char func[16];
      static char query_stmt[] = "SELECT NEXTVAL('Cns_unique_id')";
      PGresult *res;

      strcpy (func, "Cns_unique_id");

      res = PQexec (dbfd->Pconn, query_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      *unique_id = strtou64 (PQgetvalue (res, 0, 0));
      PQclear (res);
      return (0);
}

Cns_update_class_entry(dbfd, rec_addr, class_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_class_metadata *class_entry;
{
      char func[23];
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_class_metadata SET \
            NAME = '%s', OWNER_UID = %d, GID = %d, MIN_FILESIZE = %d, \
            MAX_FILESIZE = %d, FLAGS = %d, MAXDRIVES = %d, \
            MAX_SEGSIZE = %d, MIGR_TIME_INTERVAL = %d, \
            MINTIME_BEFOREMIGR = %d, NBCOPIES = %d, \
            NBDIRS_USING_CLASS = %d, RETENP_ON_DISK = %d \
            WHERE ROWID = %s";

      strcpy (func, "Cns_update_class_entry");
      sprintf (sql_stmt, update_stmt,
          class_entry->name, class_entry->uid, class_entry->gid,
          class_entry->min_filesize, class_entry->max_filesize,
          class_entry->flags, class_entry->maxdrives,
          class_entry->max_segsize, class_entry->migr_time_interval,
          class_entry->mintime_beforemigr, class_entry->nbcopies,
          class_entry->nbdirs_using_class, class_entry->retenp_on_disk,
          *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_update_fmd_entry(dbfd, rec_addr, fmd_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_file_metadata *fmd_entry;
{
      char escaped_name[CA_MAXNAMELEN*2+1];
      char filesize_str[21];
      char func[21];
      char parent_fileid_str[21];
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_file_metadata SET \
            PARENT_FILEID = %s, GUID = '%s', NAME = '%s', FILEMODE = %d, \
            NLINK = %d, OWNER_UID = %d, GID = %d, FILESIZE = %s, ATIME = %d, \
            MTIME = %d, CTIME = %d, FILECLASS = %d, STATUS = '%c', \
            CSUMTYPE = '%s', CSUMVALUE = '%s', ACL = '%s' \
            WHERE ROWID = %s";
      static char update_stmt_null_guid[] =
            "UPDATE Cns_file_metadata SET \
            PARENT_FILEID = %s, GUID = NULL, NAME = '%s', FILEMODE = %d, \
            NLINK = %d, OWNER_UID = %d, GID = %d, FILESIZE = %s, ATIME = %d, \
            MTIME = %d, CTIME = %d, FILECLASS = %d, STATUS = '%c', \
            CSUMTYPE = '%s', CSUMVALUE = '%s', ACL = '%s' \
            WHERE ROWID = %s";

      strcpy (func, "Cns_update_fmd_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, fmd_entry->name,
          strlen (fmd_entry->name), NULL);
      if (*fmd_entry->guid)
            sprintf (sql_stmt, update_stmt,
                u64tostr (fmd_entry->parent_fileid, parent_fileid_str, -1),
                fmd_entry->guid, escaped_name, fmd_entry->filemode, fmd_entry->nlink,
                fmd_entry->uid, fmd_entry->gid,
                u64tostr (fmd_entry->filesize, filesize_str, -1),
                fmd_entry->atime, fmd_entry->mtime, fmd_entry->ctime,
                fmd_entry->fileclass, fmd_entry->status, fmd_entry->csumtype,
                fmd_entry->csumvalue, fmd_entry->acl, *rec_addr);
      else  /* must insert a NULL guid and not an empty string because of
               the UNIQUE constraint on guid */
            sprintf (sql_stmt, update_stmt_null_guid,
                u64tostr (fmd_entry->parent_fileid, parent_fileid_str, -1),
                escaped_name, fmd_entry->filemode, fmd_entry->nlink,
                fmd_entry->uid, fmd_entry->gid,
                u64tostr (fmd_entry->filesize, filesize_str, -1),
                fmd_entry->atime, fmd_entry->mtime, fmd_entry->ctime,
                fmd_entry->fileclass, fmd_entry->status, fmd_entry->csumtype,
                fmd_entry->csumvalue, fmd_entry->acl, *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_update_rep_entry(dbfd, rec_addr, rep_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_file_replica *rep_entry;
{
      char escaped_name[CA_MAXSFNLEN*2+1];
      char func[21];
      char nbacces_str[21];
      PGresult *res;
      char sql_stmt[2689];
      static char update_stmt[] =
            "UPDATE Cns_file_replica SET \
            NBACCESSES = %s, CTIME = %d, ATIME = %d, PTIME = %d, \
            LTIME = %d, R_TYPE = '%c', STATUS = '%c', \
            F_TYPE = '%c', SETNAME = '%s', POOLNAME = '%s', HOST = '%s', \
            FS = '%s', SFN = '%s' \
            WHERE ROWID = %s";
      static char update_stmt_null_ftype[] =
            "UPDATE Cns_file_replica SET \
            NBACCESSES = %s, CTIME = %d, ATIME = %d, PTIME = %d, \
            LTIME = %d, R_TYPE = '%c', STATUS = '%c', \
            F_TYPE = NULL, SETNAME = '%s', POOLNAME = '%s', HOST = '%s', \
            FS = '%s', SFN = '%s' \
            WHERE ROWID = %s";
      static char update_stmt_null_rtype[] =
            "UPDATE Cns_file_replica SET \
            NBACCESSES = %s, CTIME = %d, ATIME = %d, PTIME = %d, \
            LTIME = %d, R_TYPE = NULL, STATUS = '%c', \
            F_TYPE = '%c', SETNAME = '%s', POOLNAME = '%s', HOST = '%s', \
            FS = '%s', SFN = '%s' \
            WHERE ROWID = %s";
      static char update_stmt_null_types[] =
            "UPDATE Cns_file_replica SET \
            NBACCESSES = %s, CTIME = %d, ATIME = %d, PTIME = %d, \
            LTIME = %d, R_TYPE = NULL, STATUS = '%c', \
            F_TYPE = NULL, SETNAME = '%s', POOLNAME = '%s', HOST = '%s', \
            FS = '%s', SFN = '%s' \
            WHERE ROWID = %s";

      strcpy (func, "Cns_update_rep_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, rep_entry->sfn,
          strlen (rep_entry->sfn), NULL);
      if (rep_entry->f_type) {
            if (rep_entry->r_type)
                  sprintf (sql_stmt, update_stmt,
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->r_type, rep_entry->status,
                      rep_entry->f_type, rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name, *rec_addr);
            else
                  sprintf (sql_stmt, update_stmt_null_rtype,
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->status,
                      rep_entry->f_type, rep_entry->setname, rep_entry->poolname,
                      rep_entry->host, rep_entry->fs, escaped_name, *rec_addr);
      } else {
            if (rep_entry->r_type)
                  sprintf (sql_stmt, update_stmt_null_ftype,
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->r_type, rep_entry->status,
                      rep_entry->setname, rep_entry->poolname, rep_entry->host,
                      rep_entry->fs, escaped_name, *rec_addr);
            else
                  sprintf (sql_stmt, update_stmt_null_types,
                      u64tostr (rep_entry->nbaccesses, nbacces_str, -1),
                      rep_entry->ctime, rep_entry->atime, rep_entry->ptime,
                      rep_entry->ltime, rep_entry->status,
                      rep_entry->setname, rep_entry->poolname, rep_entry->host,
                      rep_entry->fs, escaped_name, *rec_addr);
      }

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_update_smd_entry(dbfd, rec_addr, smd_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_seg_metadata *smd_entry;
{
      char func[21];
      PGresult *res;
      char segsize_str[21];
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_seg_metadata SET \
            SEGSIZE     = %s, COMPRESSION = %d, S_STATUS = '%c', \
            VID = '%s', SIDE = %d, FSEQ = %d, BLOCKID = '%02x%02x%02x%02x', \
            WHERE ROWID = %s";

      strcpy (func, "Cns_update_smd_entry");
      sprintf (sql_stmt, update_stmt,
          u64tostr (smd_entry->segsize, segsize_str, -1),
          smd_entry->compression, smd_entry->s_status,
          smd_entry->vid, smd_entry->side, smd_entry->fseq,
          smd_entry->blockid[0], smd_entry->blockid[1],
          smd_entry->blockid[2], smd_entry->blockid[3],
          *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_update_umd_entry(dbfd, rec_addr, umd_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_user_metadata *umd_entry;
{
      char func[21];
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_user_metadata SET \
            COMMENTS = '%s' \
            WHERE ROWID = %s";

      strcpy (func, "Cns_update_umd_entry");
      sprintf (sql_stmt, update_stmt,
          umd_entry->comments, *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

      /* Routines for identity mapping */

Cns_delete_group_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_groupinfo WHERE ROWID = %s";
      char func[23];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_group_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_delete_user_entry(dbfd, rec_addr)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
{
      static char delete_stmt[] =
            "DELETE FROM Cns_userinfo WHERE ROWID = %s";
      char func[22];
      PGresult *res;
      char sql_stmt[70];

      strcpy (func, "Cns_delete_user_entry");
      sprintf (sql_stmt, delete_stmt, *rec_addr);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_get_grpinfo_by_gid(dbfd, gid, group_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
gid_t gid;
struct Cns_groupinfo *group_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[23];
      int i = 0;
      static char query[] =
            "SELECT GID, GROUPNAME FROM Cns_groupinfo \
            WHERE gid = %d";
      static char query4upd[] =
            "SELECT ROWID, GID, GROUPNAME FROM Cns_groupinfo \
            WHERE gid = %d FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_grpinfo_by_gid");
      sprintf (sql_stmt, lock ? query4upd : query, gid);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, i++));
      group_entry->gid = atoi (PQgetvalue (res, 0, i++));
      strcpy (group_entry->groupname, PQgetvalue (res, 0, i));
      PQclear (res);
      return (0);
}

Cns_get_grpinfo_by_name(dbfd, name, group_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
char *name;
struct Cns_groupinfo *group_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[24];
      int i = 0;
      static char query[] =
            "SELECT GID, GROUPNAME FROM Cns_groupinfo \
            WHERE groupname = '%s'";
      static char query4upd[] =
            "SELECT ROWID, GID, GROUPNAME FROM Cns_groupinfo \
            WHERE groupname = '%s' FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_grpinfo_by_name");
      sprintf (sql_stmt, lock ? query4upd : query, name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, i++));
      group_entry->gid = atoi (PQgetvalue (res, 0, i++));
      strcpy (group_entry->groupname, PQgetvalue (res, 0, i));
      PQclear (res);
      return (0);
}

Cns_get_usrinfo_by_name(dbfd, name, user_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
char *name;
struct Cns_userinfo *user_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char escaped_name[255*2+1];
      char func[24];
      int i = 0;
      static char query[] =
            "SELECT USERID, USERNAME FROM Cns_userinfo \
            WHERE username = '%s'";
      static char query4upd[] =
            "SELECT ROWID, USERID, USERNAME FROM Cns_userinfo \
            WHERE username = '%s' FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_usrinfo_by_name");
      PQescapeStringConn (dbfd->Pconn, escaped_name, name, strlen (name), NULL);
      sprintf (sql_stmt, lock ? query4upd : query, escaped_name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, i++));
      user_entry->userid = atoi (PQgetvalue (res, 0, i++));
      strcpy (user_entry->username, PQgetvalue (res, 0, i));
      PQclear (res);
      return (0);
}

Cns_get_usrinfo_by_uid(dbfd, uid, user_entry, lock, rec_addr)
struct Cns_dbfd *dbfd;
uid_t uid;
struct Cns_userinfo *user_entry;
int lock;
Cns_dbrec_addr *rec_addr;
{
      char func[23];
      int i = 0;
      static char query[] =
            "SELECT USERID, USERNAME FROM Cns_userinfo \
            WHERE userid = %d";
      static char query4upd[] =
            "SELECT ROWID, USERID, USERNAME FROM Cns_userinfo \
            WHERE userid = %d FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_get_usrinfo_by_uid");
      sprintf (sql_stmt, lock ? query4upd : query, uid);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            serrno = ENOENT;
            return (-1);
      }
      if (lock)
            strcpy (*rec_addr, PQgetvalue (res, 0, i++));
      user_entry->userid = atoi (PQgetvalue (res, 0, i++));
      strcpy (user_entry->username, PQgetvalue (res, 0, i));
      PQclear (res);
      return (0);
}

Cns_insert_group_entry(dbfd, group_entry)
struct Cns_dbfd *dbfd;
struct Cns_groupinfo *group_entry;
{
      char func[23];
      static char insert_stmt[] =
            "INSERT INTO Cns_groupinfo (GID, GROUPNAME) VALUES (%d, '%s')";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_group_entry");
      sprintf (sql_stmt, insert_stmt, group_entry->gid, group_entry->groupname);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_insert_user_entry(dbfd, user_entry)
struct Cns_dbfd *dbfd;
struct Cns_userinfo *user_entry;
{
      char escaped_name[255*2+1];
      char func[22];
      static char insert_stmt[] =
            "INSERT INTO Cns_userinfo (USERID, USERNAME) VALUES (%d, '%s')";
      PGresult *res;
      char sql_stmt[1024];

      strcpy (func, "Cns_insert_user_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, user_entry->username,
          strlen (user_entry->username), NULL);
      sprintf (sql_stmt, insert_stmt, user_entry->userid, escaped_name);
      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "INSERT", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

int oneuniquegid;
Cns_unique_gid(dbfd, unique_id)
struct Cns_dbfd *dbfd;
unsigned int *unique_id;
{
      char func[15];
      static char insert_stmt[] =
            "INSERT INTO Cns_unique_gid (ID) VALUES (101)";
      static char query_stmt[] =
            "SELECT ID FROM Cns_unique_gid FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];
      unsigned int uniqueid;
      static char update_stmt[] =
            "UPDATE Cns_unique_gid SET ID = %d";

      strcpy (func, "Cns_unique_gid");
      (void) Cthread_mutex_lock (&oneuniquegid);
      res = PQexec (dbfd->Pconn, query_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            (void) Cthread_mutex_unlock (&oneuniquegid);
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            res = PQexec (dbfd->Pconn, insert_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniquegid);
                  Cns_libpq_error (func, "INSERT", res, dbfd);
                  return (-1);
            }
            *unique_id = 101;
      } else {
            uniqueid = atoi (PQgetvalue (res, 0, 0)) + 1;
            PQclear (res);
            sprintf (sql_stmt, update_stmt, uniqueid);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniquegid);
                  Cns_libpq_error (func, "UPDATE", res, dbfd);
                  return (-1);
            }
            *unique_id = uniqueid;
      }
      (void) Cthread_mutex_unlock (&oneuniquegid);
      PQclear (res);
      return (0);
}

int oneuniqueuid;
Cns_unique_uid(dbfd, unique_id)
struct Cns_dbfd *dbfd;
unsigned int *unique_id;
{
      char func[15];
      static char insert_stmt[] =
            "INSERT INTO Cns_unique_uid (ID) VALUES (101)";
      static char query_stmt[] =
            "SELECT ID FROM Cns_unique_uid FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];
      unsigned int uniqueid;
      static char update_stmt[] =
            "UPDATE Cns_unique_uid SET ID = %d";

      strcpy (func, "Cns_unique_uid");
      (void) Cthread_mutex_lock (&oneuniqueuid);
      res = PQexec (dbfd->Pconn, query_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            (void) Cthread_mutex_unlock (&oneuniqueuid);
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            res = PQexec (dbfd->Pconn, insert_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniqueuid);
                  Cns_libpq_error (func, "INSERT", res, dbfd);
                  return (-1);
            }
            *unique_id = 101;
      } else {
            uniqueid = atoi (PQgetvalue (res, 0, 0)) + 1;
            PQclear (res);
            sprintf (sql_stmt, update_stmt, uniqueid);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniqueuid);
                  Cns_libpq_error (func, "UPDATE", res, dbfd);
                  return (-1);
            }
            *unique_id = uniqueid;
      }
      (void) Cthread_mutex_unlock (&oneuniqueuid);
      PQclear (res);
      return (0);
}

Cns_update_group_entry(dbfd, rec_addr, group_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_groupinfo *group_entry;
{
      char func[23];
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_groupinfo SET GROUPNAME = '%s' WHERE ROWID = %s";

      strcpy (func, "Cns_update_group_entry");
      sprintf (sql_stmt, update_stmt, group_entry->groupname, *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Cns_update_unique_gid(dbfd, unique_id)
struct Cns_dbfd *dbfd;
unsigned int unique_id;
{
      char func[22];
      static char insert_stmt[] =
            "INSERT INTO Cns_unique_gid (ID) VALUES (%d)";
      static char query_stmt[] =
            "SELECT ID FROM Cns_unique_gid FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_unique_gid SET ID = %d";

      strcpy (func, "Cns_update_unique_gid");
      (void) Cthread_mutex_lock (&oneuniquegid);
      res = PQexec (dbfd->Pconn, query_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            (void) Cthread_mutex_unlock (&oneuniquegid);
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            sprintf (sql_stmt, insert_stmt, unique_id);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniquegid);
                  Cns_libpq_error (func, "INSERT", res, dbfd);
                  return (-1);
            }
      } else {
            if (unique_id > atoi (PQgetvalue (res, 0, 0))) {
                  PQclear (res);
                  sprintf (sql_stmt, update_stmt, unique_id);
                  res = PQexec (dbfd->Pconn, sql_stmt);
                  if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                        (void) Cthread_mutex_unlock (&oneuniquegid);
                        Cns_libpq_error (func, "UPDATE", res, dbfd);
                        return (-1);
                  }
            }
      }
      (void) Cthread_mutex_unlock (&oneuniquegid);
      PQclear (res);
      return (0);
}

Cns_update_unique_uid(dbfd, unique_id)
struct Cns_dbfd *dbfd;
unsigned int unique_id;
{
      char func[22];
      static char insert_stmt[] =
            "INSERT INTO Cns_unique_uid (ID) VALUES (%d)";
      static char query_stmt[] =
            "SELECT ID FROM Cns_unique_uid FOR UPDATE";
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_unique_uid SET ID = %d";

      strcpy (func, "Cns_update_unique_uid");
      (void) Cthread_mutex_lock (&oneuniqueuid);
      res = PQexec (dbfd->Pconn, query_stmt);
      if (PQresultStatus (res) != PGRES_TUPLES_OK) {
            (void) Cthread_mutex_unlock (&oneuniqueuid);
            Cns_libpq_error (func, "SELECT", res, dbfd);
            return (-1);
      }
      if (PQntuples (res) == 0) {
            PQclear (res);
            sprintf (sql_stmt, insert_stmt, unique_id);
            res = PQexec (dbfd->Pconn, sql_stmt);
            if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                  (void) Cthread_mutex_unlock (&oneuniqueuid);
                  Cns_libpq_error (func, "INSERT", res, dbfd);
                  return (-1);
            }
      } else {
            if (unique_id > atoi (PQgetvalue (res, 0, 0))) {
                  PQclear (res);
                  sprintf (sql_stmt, update_stmt, unique_id);
                  res = PQexec (dbfd->Pconn, sql_stmt);
                  if (PQresultStatus (res) != PGRES_COMMAND_OK) {
                        (void) Cthread_mutex_unlock (&oneuniqueuid);
                        Cns_libpq_error (func, "UPDATE", res, dbfd);
                        return (-1);
                  }
            }
      }
      (void) Cthread_mutex_unlock (&oneuniqueuid);
      PQclear (res);
      return (0);
}

Cns_update_user_entry(dbfd, rec_addr, user_entry)
struct Cns_dbfd *dbfd;
Cns_dbrec_addr *rec_addr;
struct Cns_userinfo *user_entry;
{
      char escaped_name[255*2+1];
      char func[22];
      PGresult *res;
      char sql_stmt[1024];
      static char update_stmt[] =
            "UPDATE Cns_userinfo SET USERNAME = '%s' WHERE ROWID = %s";

      strcpy (func, "Cns_update_user_entry");
      PQescapeStringConn (dbfd->Pconn, escaped_name, user_entry->username,
          strlen (user_entry->username), NULL);
      sprintf (sql_stmt, update_stmt, escaped_name, *rec_addr);

      res = PQexec (dbfd->Pconn, sql_stmt);
      if (PQresultStatus (res) != PGRES_COMMAND_OK) {
            if (strstr (PQresultErrorMessage (res), "duplicate")) {
                  serrno = EEXIST;
                  PQclear (res);
            } else
                  Cns_libpq_error (func, "UPDATE", res, dbfd);
            return (-1);
      }
      PQclear (res);
      return (0);
}

Generated by  Doxygen 1.6.0   Back to index