/* BLURB gpl

                           Coda File System
                              Release 6

          Copyright (c) 1987-2003 Carnegie Mellon University
                  Additional copyrights listed below

This  code  is  distributed "AS IS" without warranty of any kind under
the terms of the GNU General Public Licence Version 2, as shown in the
file  LICENSE.  The  technical and financial  contributors to Coda are
listed in the file CREDITS.

                        Additional copyrights
                           none currently

#*/

/*
 * Very simple program query the volume databases on Coda servers, it sets up
 * an rpc2 connection and performs a ViceGetVolumeInfo query.
 * 
 *   Jan Harkes, July 2001
 */

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <lwp/lwp.h>
#include <rpc2/rpc2.h>
#include <ports.h>
#include <coda_string.h>

#include "vice.h"

void Initialize(void)
{
    PROCESS pid;
    struct timeval tv;
    long rc;

    /* initialize the subsystems LWP/RPC */
    rc = LWP_Init(LWP_VERSION, LWP_NORMAL_PRIORITY, &pid);
    if (rc != LWP_SUCCESS) {
	printf("LWP_Init() failed\n");
	exit(-1);
    }

    tv.tv_sec = 15;
    tv.tv_usec = 0;
    rc = RPC2_Init(RPC2_VERSION, 0, 0, -1, &tv);
    if (rc != LWP_SUCCESS) {
	printf("RPC_Init() failed\n");
	exit(-1);
    }
}

long Bind(char *host, short port, long subsys, RPC2_Handle *cid)
{
    RPC2_HostIdent   hostid;
    RPC2_PortIdent   portid;
    RPC2_SubsysIdent subsysid;
    RPC2_BindParms   bindparms;

    /* Initialize connection stuff */
    hostid.Tag = RPC2_HOSTBYNAME;
    strcpy(hostid.Value.Name, host);

    portid.Tag = RPC2_PORTBYINETNUMBER;
    portid.Value.InetPortNumber = htons(port);

    subsysid.Tag = RPC2_SUBSYSBYID;
    subsysid.Value.SubsysId= subsys;

    bindparms.SideEffectType = 0;
    bindparms.SecurityLevel = RPC2_OPENKIMONO;
    bindparms.ClientIdent = 0;

    return RPC2_NewBinding(&hostid, &portid, &subsysid, &bindparms, cid);
}

static char *viceaddr(unsigned long srvaddr)
{
    unsigned long netaddr = htonl(srvaddr);
    struct in_addr host = *(struct in_addr *)&netaddr;
    return inet_ntoa(host);
}

int main(int argc, char *argv[])
{
    RPC2_Handle cid;
    long        rc;
    char       *host, *volume;
    short       port;
    long	subsys;
    VolumeInfo  volinfo;

    if (argc <= 2)
        goto badargs;

    subsys = SUBSYS_SRV;

    if (strcmp(argv[1], "-p") == 0) {
        if (argc <= 4)
            goto badargs;

        host = argv[3];
        volume = argv[4];
        port = atoi(argv[2]);
    } else {
        host = argv[1];
        volume = argv[2];
        port = PORT_codasrv; /* codasrv portnumber */
    }

    Initialize();

    rc = Bind(host, port, subsys, &cid);

    if (rc != RPC2_SUCCESS) {
        printf("RPC2 connection to %s:%d failed with %s.\n",
               host, port, RPC2_ErrorMsg(rc));
        exit(2);
    }
    printf("RPC2 connection to %s:%d successful.\n", host, port);

    rc = ViceGetVolumeInfo(cid, volume, &volinfo);

    if (rc != RPC2_SUCCESS) {
        printf("ViceGetVolumeInfo for %s to %s:%d failed with %s.\n",
               volume, host, port, RPC2_ErrorMsg(rc));
	RPC2_Unbind(cid);
        exit(3);
    }

    printf("Returned volume information for %s\n", volume);
    printf("\tVolumeId %lx\n", volinfo.Vid);
    switch(volinfo.Type) {
    case ReadOnly:
	printf("\tReadonly clone (type %ld)\n", volinfo.Type);
	break;

    case ReadWrite:
	printf("\tReadwrite underlying volume replica (type %ld)\n", volinfo.Type);
	break;

    case Backup:
	printf("\tBackup volume (type %ld)\n", volinfo.Type);
	break;

    case Replicated:
	printf("\tReplicated volume (type %ld)\n", volinfo.Type);
	break;

    default:
	printf("\tUnknown volume type %ld\n", volinfo.Type);
	break;
    }
    printf("\n");
    printf("\tType0 id %lx\n", volinfo.Type0);
    printf("\tType1 id %lx\n", volinfo.Type1);
    printf("\tType2 id %lx\n", volinfo.Type2);
    printf("\tType3 id %lx\n", volinfo.Type3);
    printf("\tType4 id %lx\n", volinfo.Type4);
    printf("\n");
    printf("\tServerCount %ld\n", volinfo.ServerCount);
    printf("\tReplica0 id %08lx, Server0 %s\n",
	   volinfo.RepVolMap.Volume0, viceaddr(volinfo.Server0));
    printf("\tReplica1 id %08lx, Server1 %s\n",
	   volinfo.RepVolMap.Volume1, viceaddr(volinfo.Server1));
    printf("\tReplica2 id %08lx, Server2 %s\n",
	   volinfo.RepVolMap.Volume2, viceaddr(volinfo.Server2));
    printf("\tReplica3 id %08lx, Server3 %s\n",
	   volinfo.RepVolMap.Volume3, viceaddr(volinfo.Server3));
    printf("\tReplica4 id %08lx, Server4 %s\n",
	   volinfo.RepVolMap.Volume4, viceaddr(volinfo.Server4));
    printf("\tReplica5 id %08lx, Server5 %s\n",
	   volinfo.RepVolMap.Volume5, viceaddr(volinfo.Server5));
    printf("\tReplica6 id %08lx, Server6 %s\n",
	   volinfo.RepVolMap.Volume6, viceaddr(volinfo.Server6));
    printf("\tReplica7 id %08lx, Server7 %s\n",
	   volinfo.RepVolMap.Volume7, viceaddr(volinfo.Server7));
    printf("\n");
    printf("\tVSGAddr %lX\n", volinfo.VSGAddr);
    printf("\n");

    RPC2_Unbind(cid);
    exit(0);

badargs:
    printf("Usage %s [-p port] hostname volumename/id\n", argv[0]);
    exit(-1);
}

