text:
/*
 * Copyright © 2012-2016 VMware, Inc.  All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the “License”); you may not
 * use this file except in compliance with the License.  You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an “AS IS” BASIS, without
 * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
#include "certool.h"
#include <vmca.h>
#include <vmcacommon.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <vmca_error.h>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#ifndef __NO_AFD__
#include <vmafdclient.h>
#endif

#if _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#define snprintf _snprintf
#define sleep Sleep
#endif // _MSC_VER

std::string FriendlyName;

const size_t CERTOOL_PRIVATE_KEY_LENGTH = 2048;

//
// This file is written as a sample code for the end user.
// Hence this file will be overly verbose.
// Please bear with the example style of commenting.
//

static DWORD
_HandleOpenServer(
    PVMCA_SERVER_CONTEXT *ppServer
    )
{
    DWORD dwError = 0;
    PVMCA_SERVER_CONTEXT hServer = NULL;

    dwError = VMCAOpenServerA(
                  (PCSTR) argServerName.c_str(),
                  (PCSTR) argSrpUpn.c_str(),
                  NULL,
                  (PCSTR) argSrpPwd.c_str(),
                  0, //flags
                  NULL, // Reserved
                  &hServer);
    BAIL_ON_ERROR(dwError);

    *ppServer = hServer;

error:
    return dwError;
}

static
DWORD
UpdateReqData(PVMCA_PKCS_10_REQ_DATAA pCertReqData)
{
    DWORD dwError = ERROR_SUCCESS;

    if ( cfgName.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_CN,
                  pCertReqData, (PSTR)cfgName.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if (cfgDomainComponent.length() > 0)
    {
        dwError = VMCASetCertValueA(
                                    VMCA_OID_DC,
                                    pCertReqData,
                                    (PSTR)cfgDomainComponent.c_str()
                                   );
        BAIL_ON_ERROR(dwError);
    }

    if(cfgCountry.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_COUNTRY,
                  pCertReqData, (PSTR)cfgCountry.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgLocality.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_LOCALITY,
                  pCertReqData, (PSTR)cfgLocality.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if (cfgState.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_STATE,
                  pCertReqData, (PSTR)cfgState.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgOrganization.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_ORGANIZATION,
                  pCertReqData,(PSTR) cfgOrganization.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgOrgUnit.length()>0) {
      dwError = VMCASetCertValueA( VMCA_OID_ORG_UNIT,
                  pCertReqData, (PSTR)cfgOrgUnit.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgHostName.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_DNS,
                  pCertReqData, (PSTR)cfgHostName.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgEmail.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_EMAIL,
                pCertReqData, (PSTR)cfgEmail.c_str());
      BAIL_ON_ERROR(dwError);
    }

    if(cfgIPAddress.length() > 0) {
      dwError = VMCASetCertValueA( VMCA_OID_IPADDRESS,
          pCertReqData, (PSTR)cfgIPAddress.c_str());
      BAIL_ON_ERROR(dwError);
    }

cleanup:
    return dwError;
error:
    goto cleanup;
}

DWORD
HandleInitCSR()

//
// This function generates a Root CA CSR , A private Key and Public Key for
// CA Certificates use, In order to use this CSR the generated file must
// taken to a CA that can sign the certificate and return it to us.
//
// Here are the steps in the initCSR creation process
//  1) We need to create a Public/Private Key Pair
//  2) Create a Certificate Signing Request Object -- which is PVMCA_PKCS_10_REQ_DATAA
//  3) Populate all fields that we are intersted in
//  4) Sign the CSR with our Private Key -- Please note: Private key never leaves our machine
//  5) Write the Private Key, Public Key and CSR to  user specified location
//
{

    DWORD dwError = 0;
    PVMCA_KEY pPrivateKey = NULL;
    PVMCA_KEY pPublicKey = NULL;
    PVMCA_PKCS_10_REQ_DATAA pCertReqData = NULL;
    PVMCA_CSR pCSR = NULL;
    PVMCA_CERTIFICATE pCertificate = NULL;

    std::ofstream oPrivatefile;
    std::ofstream oPublicfile;
    std::ofstream oCSRfile;

//
// Step 1: Create a Public / Private Key Pair
// The Key Length is set to 1024, Password is set to NULL
//
    dwError = VMCACreatePrivateKey( NULL, CERTOOL_PRIVATE_KEY_LENGTH, &pPrivateKey, &pPublicKey );
    BAIL_ON_ERROR(dwError);
//
// Step 2: Create a Certificate Signing Request Object
//
    dwError = VMCAAllocatePKCS10DataA(&pCertReqData);
    BAIL_ON_ERROR(dwError);

    dwError = UpdateReqData(pCertReqData);
    BAIL_ON_ERROR(dwError);

//
// Step 4: Create a Signing Request CSR ( PKCS10)
//
    dwError =  VMCACreateSigningRequestA(
                   pCertReqData,
                   pPrivateKey,
                   NULL,
                   &pCSR);
    BAIL_ON_ERROR(dwError);
//
// Step 5 :
// write the private key to a location specified by the user
// This for illustration purpose only, you can also use
// VMCAWritePrivateKeyToFile which will handle things like Password on the
// Private Key.
//
    oPrivatefile.open (argPrivateKey.c_str());
    oPrivatefile << pPrivateKey;
    oPrivatefile.close();

    oPublicfile.open (argPublicKey.c_str());
    oPublicfile << pPublicKey;
    oPrivatefile.close();

    oCSRfile.open(argCsr.c_str());
    oCSRfile << pCSR;
    oCSRfile.close();

error:
    VMCAFreeKey(pPrivateKey);
    VMCAFreeKey(pPublicKey);
    VMCAFreePKCS10DataA(pCertReqData);
    VMCAFreeCSR(pCSR);
    VMCAFreeCertificate(pCertificate);

    return dwError;
}

VOID
VMCAGetGMTime( time_t tm, time_t *pUtcTime)
{
#ifndef _WIN32
    struct tm ptm = {0};
    gmtime_r(&tm, &ptm);
    *pUtcTime = timegm(&ptm);
#else
    struct tm* tptr = NULL;
    tptr = gmtime( &tm );
    *pUtcTime = _mkgmtime(tptr);
#endif
}

DWORD
HandleCreateSelfSignedCA()
//
// This function generates a Root CA Certificate and uploads that
// to VMCA Server
// In order to generate a Self Signed Certificate, we need to create
// a bunch of artifacts, whichSelf when combined will produce a Certificate.
//
//  1) We need to create a Public/Private Key Pair
//  2) Create a Certificate Signing Request Object -- which is PVMCA_PKCS_10_REQ_DATAA
//  3) Populate all fields that we are intersted in
//  4) Sign the CSR with our Private Key -- Please note: Private key never leaves our machine
//  5) Create a Local CA Certificate
//  6) Push that Certificate to the Server, so that CA can be operational
//
//
{
    #define HOST_NAME_MAX 64
    DWORD dwError = 0;
    PVMCA_KEY pPrivateKey = NULL;
    PVMCA_KEY pPublicKey = NULL;
    PVMCA_PKCS_10_REQ_DATAA pCertReqData = NULL;
    PVMCA_CSR pCSR = NULL;
    PVMCA_CERTIFICATE pCertificate = NULL;
    PSTR pszDefaultDomainName = NULL;
    PCSTR pszServer = "localhost";
    char hostName [HOST_NAME_MAX] = {0,};
    unsigned long dwMask = 0;
    time_t now = 0;
    time_t expire = 0;
    time_t UtcNow = 0;
    time_t UtcExpire = 0;
    PVMCA_SERVER_CONTEXT hServer = NULL;

#ifndef __NO_AFD__
    PVECS_STORE pStore = NULL;
#endif

//
// Step 1: Create a Public / Private Key Pair
// The Key Length is set to 1024, Password is set to NULL
//
    dwError = VMCACreatePrivateKey( NULL, CERTOOL_PRIVATE_KEY_LENGTH,
                                    &pPrivateKey, &pPublicKey);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to create key pair\n", dwError);
    }
    BAIL_ON_ERROR(dwError);
//
// Step 2: Create a Certificate Signing Request Object
//
    dwError = VMCAAllocatePKCS10DataA(&pCertReqData);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to allocate CSR\n", dwError);
    }
    BAIL_ON_ERROR(dwError);
//
// Step 3: Populate all Fields -- There are two ways to do this
// One technique is illustrated here, and another one will be done
// as a comment for the user to understand different ways of doing it
//
// all cfgVariables are globals declared in certool.cpp
// where the values where parsed from a config file
//
#ifdef _WIN32
{
    WORD wVersionRequested = 0;
    WSADATA wsaData = {0};

/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
    wVersionRequested = MAKEWORD(2, 2);

    dwError = WSAStartup(wVersionRequested, &wsaData);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to start winsock library\n", dwError);
    }
    BAIL_ON_ERROR(dwError);
}
#endif

    dwError = gethostname(hostName, HOST_NAME_MAX);
    if ( dwError != 0) {
      printf("gethostname failed, please check if host name is more \
        than 64 chars.\n");
    }
    BAIL_ON_ERROR(dwError);

#ifdef _WIN32
    WSACleanup();
#endif

    dwError = VmAfdGetDomainNameA(
                                  pszServer,
                                  &pszDefaultDomainName
                                 );
    if (dwError != 0)
    {
       printf("Warning: %d, Failed to get domain name\n", dwError);
       dwError = 0;
    }

    // Current in the cloud VM we don't wait for VMDIR
    // This would be fixed when we have one first boot.
    // Don't fail , this avoids the failure due the race condition.

    dwError = VMCAInitPKCS10DataWithDCA(
                              cfgName.c_str(),
                              pszDefaultDomainName,
                              hostName,
                              cfgOrgUnit.c_str(),
                              cfgState.c_str(),
                              cfgCountry.c_str(),
                              cfgEmail.c_str(),
                              cfgIPAddress.c_str(),
                              pCertReqData);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to create CSR\n", dwError);
    }
    BAIL_ON_ERROR(dwError);

    VMCASetBit(&dwMask, VMCA_KEY_CERT_SIGN);
    VMCASetBit(&dwMask, VMCA_KEY_CRL_SIGN);

    VMCASetKeyUsageConstraintsA(
        pCertReqData,
        dwMask );

//
// Step 5 :
// Since we are creating a Self Signed Certificate
// Here we are not making a Call to the Server.
// We generate a self signed Root CA Certificate and
// then push that certificate to the Server.
//
// Let us make the certificate valid for 10 years
// 365 days * 24 hours * 60 minutes * 60 seconds * 10
//

    time(&now);
    now = now - (argPredates * 60);
    expire = now + VMCA_DEFAULT_CA_CERT_VALIDITY;

    VMCAGetGMTime(now, &UtcNow);
    VMCAGetGMTime(expire, &UtcExpire);

    dwError =  VMCACreateSelfSignedCertificateA(
                 pCertReqData,
                 pPrivateKey,
                 NULL,
                 UtcNow,
                 UtcExpire,
                 &pCertificate);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to create root certificate\n", dwError);
    }
    BAIL_ON_ERROR(dwError);
//
// Step 6:
// Now that we have the Certificate and the Private Key,
// we should push these artifacts to the Server
//
    dwError = _HandleOpenServer(&hServer);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to open connection to server\n", dwError);
    }
    BAIL_ON_ERROR(dwError);

    /* RPC client call */
    dwError = VMCAAddRootCertificateHA(
                  hServer,
                  argServerName.c_str(),
                  pCertificate,
                  NULL,
                  pPrivateKey);
    if (dwError != 0)
    {
       printf("Error: %d, Failed to add root certificate\n", dwError);
    }
    BAIL_ON_ERROR(dwError);

//
// At this point the CA Server has a Root Certificate provisioned that
// allows the CA to start issuing Certs. VC might want to insert this
// Root CA Cert to the ESX and VC's Cert Store.
//

//
// Add VMCA Root Certificate to VECS Trusted Roots
// on the local host
#ifndef __NO_AFD__

    dwError = VecsCreateCertStoreA(
                NULL,
                TRUSTED_ROOTS_STORE_NAME,
                NULL,
                &pStore);
    if (dwError == ERROR_ALREADY_EXISTS)
    {
        dwError = VecsOpenCertStoreA(
                    NULL,
                    TRUSTED_ROOTS_STORE_NAME,
                    NULL,
                    &pStore);
    }
    if (dwError != 0)
    {
       printf("Error: %d, Failed to open certificate store\n", dwError);
    }
    BAIL_ON_ERROR(dwError);

    dwError =  VecsAddEntryA(
                   pStore,
                   CERT_ENTRY_TYPE_TRUSTED_CERT,
                   NULL,
                   pCertificate,
                   NULL, /* private key */
                   NULL, /* password */
                   1);   /* auto refresh */
    if (dwError != 0)
    {
       printf("Warning : %d, Adding Trusted Root to VECS Store Failed.\n", dwError);
       dwError = 0;
    }

#endif

error:
#ifndef __NO_AFD__
    if (pStore)
    {
        VecsCloseCertStore(pStore);
    }
#endif
    VMCAFreeKey(pPrivateKey);
    VMCAFreeKey(pPublicKey);
    VMCAFreePKCS10DataA(pCertReqData);
    VMCAFreeCSR(pCSR);
    VMCAFreeCertificate(pCertificate);
    if (pszDefaultDomainName)
    {
        VMCAFreeStringA(pszDefaultDomainName);
    }
    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    return dwError;
}

DWORD
HandleRootCACertificate()
//
// HandleRoot CA Certificate reads a CA Cert  and a Private Key
// from a file, and uploads that to the VMware CA Server. This is
// another way of Initing the CA Server.
// The Steps involved here are
//   1) Read the Cert from the File
//   2) Read the Private Key from the File
//   3) Send Both these artifacts to the Server
{

    DWORD dwError = 0;
    PVMCA_CERTIFICATE pCertificate = NULL;
    PVMCA_KEY pKey = NULL;
    PVMCA_SERVER_CONTEXT hServer = NULL;
//
// Step 1 : Read the Certificate
//
    dwError =  VMCAReadCertificateChainFromFile(
                                (LPSTR)argCert.c_str(),
                                &pCertificate
                                );
    BAIL_ON_ERROR(dwError);

//
// Step 2: Read the Private key from the File
// PLEASE NOTE : The support for password is not in the
// Command Tool, hence not supported here.
//

    dwError = VMCAReadPrivateKeyFromFile(
                  (LPSTR)argPrivateKey.c_str(),
                  NULL,
                  &pKey);
    BAIL_ON_ERROR(dwError);

//
//Step 3:
// Now that we have the Certificate and the Private Key,
// we should push these artifacts to the Server
//
    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    /* RPC client call */
    dwError = VMCAAddRootCertificateHA(
                  hServer,
                  argServerName.c_str(),
                  pCertificate,
                  NULL,
                  pKey);
    BAIL_ON_ERROR(dwError);

error :
    VMCAFreeKey(pKey);
    VMCAFreeCertificate(pCertificate);
    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    return dwError;
}

DWORD
HandleGenCert()
// HandleGenCert creates a CSR sends it to the Server
// and gets a singed certificate back.
// Here are the Steps in this algorithm
// 1) Create a PKCS10 request object
// 2) Populate it with values
// 3) Reads the  Private Key
// 4) Create a CSR
// 5) Send it to VMware certificate server to get signature
// 6) Write the certificate back to the file.
{
    DWORD dwError = 0;
    PVMCA_PKCS_10_REQ_DATAA pCertReqData = NULL;
    PVMCA_KEY pKey = NULL;
    PVMCA_CSR pCSR = NULL;
    DWORD dwCertLength = 0;
    PVMCA_CERTIFICATE pCertificate = NULL;
    unsigned long dwMask = 0;
    time_t startFrom;
    PVMCA_SERVER_CONTEXT hServer = NULL;
    time_t timeUtcNow = 0, timeUtcExpire = 0;

    //
    // Step 1: Create a Certificate Signing Request Object
    //
    dwError = VMCAAllocatePKCS10DataA(&pCertReqData);
    BAIL_ON_ERROR(dwError);

    dwError = UpdateReqData(pCertReqData);
    BAIL_ON_ERROR(dwError);

    /* Current behaviour for VMCA Clients*/
    VMCASetBit(&dwMask, VMCA_DIGITAL_SIGNATURE);
    VMCASetBit(&dwMask, VMCA_NON_REPUDIATION);
    VMCASetBit(&dwMask, VMCA_KEY_ENCIPHERMENT);

    dwError = VMCASetKeyUsageConstraintsA(
        pCertReqData,
        dwMask  );
    BAIL_ON_ERROR(dwError);

    //
    // Step 3 : Read the Private key from the File
    // PLEASE NOTE : The support for password is not in the
    // Command Tool, hence not supported here yet.
    //
    dwError = VMCAReadPrivateKeyFromFile(
                  (LPSTR)argPrivateKey.c_str(),
                  NULL,
                  &pKey);
    BAIL_ON_ERROR(dwError);

  //
  // Step 4: Create a Signing Request CSR ( PKCS10)
  //
    dwError =  VMCACreateSigningRequestA(
                   pCertReqData,
                   pKey,
                   NULL,
                   &pCSR);
    BAIL_ON_ERROR(dwError);

  //
  // Let us make the certificate valid for 6 months
  // if it is not a valid time
  // 180 days * 24 hours * 60 minutes * 60 seconds
  //
    if ( now == 0 )
    {
      time(&now);
    }
    startFrom = now - VMCA_CERT_EXPIRY_START_LAG;
      /* The certificate is predated by 10
       * minutes to avoid time-sync issues
       */
    expire = startFrom + VMCA_DEFAULT_CERT_VALIDITY;

    VMCAGetGMTime(startFrom, &timeUtcNow);
    VMCAGetGMTime(expire, &timeUtcExpire);

  //
  // Step 5: Send the CSR to server to get it signed
  //
    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    /* RPC client call */
    dwError =  VMCAGetSignedCertificateFromCSRHA(
                   hServer,
                   argServerName.c_str(),
                   pCSR,
                   timeUtcNow,
                   timeUtcExpire,
                   &pCertificate);
    BAIL_ON_ERROR(dwError);

  //
  // Step 6 : Write the Certificate to a file
  // In the VC / ESX world you will write this to
  // the certificate store, that will also have the
  // VMCA Root Certificate that will allow you to verify
  // the trust.
  //

  dwError =  VMCAWriteCertificateChainToFile(
                       (LPSTR) argCert.c_str(),
                       pCertificate);

    BAIL_ON_ERROR(dwError);

error :
    VMCAFreePKCS10DataA(pCertReqData);
    VMCAFreeKey(pKey);
    VMCAFreeCSR(pCSR);
    VMCAFreeCertificate(pCertificate);
    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    return dwError;
}

DWORD
HandleGenKey()
//
// This function generates a Private / Public Key pair and
// write it down to a file.
//
// Here are the steps
//  1) Create Key Pair
//  2) Write to files
//
{
    DWORD dwError = 0;
    PVMCA_KEY pPrivateKey = NULL;
    PVMCA_KEY pPublicKey = NULL;
//
// Step 1: Create a Public / Private Key Pair
// The Key Length is set to 1024, Password is set to NULL
//
    dwError = VMCACreatePrivateKey( NULL, CERTOOL_PRIVATE_KEY_LENGTH, &pPrivateKey, &pPublicKey );
    BAIL_ON_ERROR(dwError);
//
// Step 2.1 Write Private key to a file
//
    dwError =  VMCAWritePrivateKeyToFile(
                   (LPSTR) argPrivateKey.c_str(),
                   (LPSTR) pPrivateKey,
                   NULL,
                   NULL);
    BAIL_ON_ERROR(dwError);

//
// Step 2.2 Write Public Key to File
//
    dwError = VMCAWritePublicKeyToFile(
                  (LPSTR) argPublicKey.c_str(),
                  (LPSTR) pPublicKey
              );
    BAIL_ON_ERROR(dwError);

error:
    VMCAFreeKey(pPublicKey);
    VMCAFreeKey(pPrivateKey);

    return dwError;
}

DWORD
HandleRevokeCert()
// This function calls into VMCA and revokes a given certificate
// Here is the Algorithm to do that
//  1) Read the Certificate from a file
//  2) Send it across to Server asking it to be revoked
//
{
    DWORD dwError = 0;
    PVMCA_CERTIFICATE pCert = NULL;
    PVMCA_SERVER_CONTEXT hServer = NULL;
//
// Step 1: Read the Certificate from File
//
    dwError = VMCAReadCertificateFromFile(
                  (LPSTR)argCert.c_str(),
                  &pCert);
    BAIL_ON_ERROR(dwError);
//
// Step 2: Call into Server to revoke the Certificate
//
    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    dwError = VMCARevokeCertA(
                  hServer,
                  (PCSTR) argServerName.c_str(),
                  (PSTR) pCert,
                  VMCA_CRL_REASON_UNSPECIFIED
                  );
    BAIL_ON_ERROR (dwError);

error :
    VMCAFreeCertificate(pCert);
    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    return dwError;
}

DWORD
HandleViewCert()
// This function demonstrates the use of
// GetCertificate as a String.
// 1) Read the Certificate
// 2) Ask VMCA to convert it into a printable String
//
{

    DWORD dwError = 0;
    PSTR pszCertString = NULL;
    PVMCA_CERTIFICATE pCert = NULL;
//
//Step 1: read the Certificate
//
    dwError = VMCAReadCertificateFromFile(
                  (LPSTR) argCert.c_str(),
                  &pCert);
    BAIL_ON_ERROR(dwError);
//
// Step 2 : Ask VMCA to convert to a printable string
//
    dwError = VMCAGetCertificateAsStringA(
                  (LPSTR) pCert,
                  &pszCertString);
    BAIL_ON_ERROR(dwError);
//
// Print it
//
    std::cout << pszCertString << std::endl;

error :
    if(pszCertString) {
        VMCA_SAFE_FREE_STRINGA(pszCertString);
    }
    VMCAFreeCertificate(pCert);

    return dwError;
}

DWORD
HandleGetRootCA()
// This function allows the users to retrive the
// Root CA Certificate that is being used for
// Signing all certificates. This certificate
// has to be trusted by all clients and generally
// this certificate will be inserted into the certificate
// store of ESX or VC.
// Algo :
// 1) Call into VMCA server and ask for Root CA Certitificate
// 2) In this case we are just printing it out to screen, but we might
// consider just inserting this to a certificate store.

{

    DWORD dwError = 0;
    DWORD dwCertLength = 0;
    PVMCA_CERTIFICATE pCert = NULL;
    PSTR pszCertString = NULL;
    PVMCA_SERVER_CONTEXT hServer = NULL;
//
// Step 1: Get the Root CA Certificate from the Server
//
    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    /* RPC client call */
    dwError = VMCAGetRootCACertificateHA(
                  hServer,
                  (PCSTR) argServerName.c_str(),
                  &pCert);
    BAIL_ON_ERROR(dwError);

    if (argCert.length() > 0)
    {

      dwError = VMCAWriteCertificateChainToFile((PSTR)argCert.c_str(),pCert);
      BAIL_ON_ERROR(dwError);
    }
//
// Convert and Print the Root CA Certificate
//
    dwError = VMCAGetCertificateAsStringA(
                  (LPSTR) pCert,
                  &pszCertString);
    BAIL_ON_ERROR(dwError);

    std::cout << pszCertString << std::endl;
    if (argCert.length() > 0) {
      std::cout << "Certificate written to file : " << argCert <<std::endl;
    }

error:
    VMCAFreeCertificate(pCert);
    if (pszCertString)
    {
        VMCA_SAFE_FREE_STRINGA(pszCertString);
    }

    if (hServer)
    {
        VMCACloseServer(hServer);
    }
    return dwError;
}

DWORD
HandleVersionRequest()
//
// This function returns a Server Version String
//
{
    DWORD dwError = 0;
    PSTR pServerVersion = NULL;
    PVMCA_SERVER_CONTEXT hServer = NULL;

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);
//
// Call into VMCA Server to get Version Number
//
    dwError =  VMCAGetServerVersionHA(
                    hServer,
                   (PCSTR) argServerName.c_str(),
                   &pServerVersion
               );
    BAIL_ON_ERROR(dwError);
//
// Print
//
    std::cout << pServerVersion << std::endl;

error:
    VMCA_SAFE_FREE_STRINGA(pServerVersion);

    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    return dwError;
}

DWORD
HandleEnumCerts()
//
// This function enumerate certificates
// 1) open enum context list
// 2) Print the certficate until done
//
{
    DWORD dwError = 0;
    DWORD dwCertLength = 0;
    PVOID pContext = NULL;
    PVMCA_CERTIFICATE pCertificate = NULL;
    PSTR pszCertString = NULL;
    int currIndex = 0;
    VMCA_ENUM_CERT_RETURN_CODE enumStatus = VMCA_ENUM_ERROR;
    VMCA_CERTIFICATE_STATUS dwStatus = VMCA_CERTIFICATE_ALL;
    PVMCA_SERVER_CONTEXT hServer = NULL;

    if ( std::strcmp(argFilter.c_str(), "active") == 0) {
        dwStatus = VMCA_CERTIFICATE_ACTIVE;
    }
    else if ( std::strcmp(argFilter.c_str(), "revoked") == 0) {
        dwStatus = VMCA_CERTIFICATE_REVOKED;
    }
    else if ( std::strcmp(argFilter.c_str(), "expired") == 0) {
        dwStatus = VMCA_CERTIFICATE_EXPIRED;
        std::cout << "This flag is not currently supported" << std::endl;
        dwError  = ERROR_NOT_SUPPORTED;
        BAIL_ON_ERROR (dwError);
    }
    else if ( std::strcmp(argFilter.c_str(), "all") == 0) {
        dwStatus = VMCA_CERTIFICATE_ALL;
    }
    else {
        goto error;
    }

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    dwError = VMCAOpenEnumContextHA(
                  hServer,
                  (PSTR)argServerName.c_str(),
                  dwStatus,
                  &pContext
              );
    BAIL_ON_ERROR(dwError);

    do {
        dwError = VMCAGetNextCertificate(
                      pContext,
                      &pCertificate,
                      &currIndex,
                      &enumStatus
                  );
        if (enumStatus == VMCA_ENUM_END)
        {
            break;
        }

        BAIL_ON_ERROR(dwError);
        std::cout << "Cert \n" << pCertificate << "\n";

        std::cerr << currIndex << std::endl;
        dwError = VMCAGetCertificateAsStringA(
                      (LPSTR) pCertificate,
                      &pszCertString);
        BAIL_ON_ERROR(dwError);

        std::cout << pszCertString << std::endl;

        VMCAFreeStringA(pszCertString);
        VMCAFreeCertificate(pCertificate);
        pszCertString = NULL;
        pCertificate = NULL;
    } while( enumStatus != VMCA_ENUM_END);

error :
    if (pContext) {
        VMCACloseEnumContext(pContext);
    }
    if (hServer) {
      VMCACloseServer(hServer);
    }
    if ( pCertificate) {
        VMCAFreeCertificate(pCertificate);
    }

    return dwError;
}

DWORD
HandleGetDC()
{
    DWORD dwError = 0;
    PSTR pDomainName = NULL;
    dwError = VMCAGetDefaultDomainName(
                  (PSTR)(argServerName.length() > 0 ? argServerName.c_str(): NULL),
                  argPort,
                  &pDomainName);
    BAIL_ON_ERROR(dwError);
    std::cout << "Default Domain Name : " << pDomainName << std::endl;

error :
    VMCA_SAFE_FREE_STRINGA(pDomainName);
    return dwError;
}

#define BUF_SIZE 1024
DWORD
HandleGenCISCert()
{
    DWORD dwError = 0;
    char CommonName [BUF_SIZE] = { 0 };
    PSTR pszDomainName = NULL;
    PSTR pszOrgUnit    = NULL;
    PSTR pszMachineID  = NULL;
    PCSTR format = "%s@%s";
    int ret = 0;
    PSTR pszCert = NULL;
    PSTR pszPrivateKey = NULL;
    PCSTR pszLocalHost = "localhost";
    std::string vecsAlias(cfgName);
#ifndef __NO_AFD__
    PVECS_STORE pStore = NULL;
#endif

    dwError = VmAfdGetMachineIDA(
                                 pszLocalHost,
                                 &pszMachineID
                                );
    BAIL_ON_ERROR(dwError);

    dwError = VMCAAllocateStringPrintfA(
                                        &pszOrgUnit,
                                        "mID-%s",
                                        pszMachineID
                                       );
    BAIL_ON_ERROR (dwError);

    cfgOrgUnit.assign(pszOrgUnit);

    if(argFQDN.length() >0)
    {
        cfgHostName.assign(argFQDN);
    }

    // CIS Cert is a Standard Form of Certs that we want to issue
    // for CIS Components in VMWare.
    // The Format is as follows
    // CN =<name>, OU = mID-<machineID>, DC=<DomainComponents>
    dwError = VmAfdGetDomainNameA(pszLocalHost, &pszDomainName);
    BAIL_ON_ERROR(dwError);

    cfgDomainComponent.assign(pszDomainName);
    if(cfgCountry.length() == 0 ) {
        cfgCountry.assign("US"); //default to US
    }

    dwError = HandleGenCert();
    BAIL_ON_ERROR(dwError);

    // Add Cert to VECS Store
    // By definition a VECS store has to be on a Local Machine.
    // However Certool might run on machines where there is
    // No VECS, so we ignore failure, and continue.

    dwError = VMCAReadCertificateFromFile((PSTR)argCert.c_str(), &pszCert);
    BAIL_ON_ERROR(dwError);

    dwError = VMCAReadPrivateKeyFromFile((PSTR)argPrivateKey.c_str(),
        NULL,  &pszPrivateKey);
    BAIL_ON_ERROR(dwError);

#ifndef __NO_AFD__
    dwError = VecsCreateCertStoreA(
                        NULL,
                        vecsAlias.c_str(),
                        NULL,
                        &pStore);
    if (dwError == ERROR_ALREADY_EXISTS)
    {
        dwError = VecsOpenCertStoreA(
                        NULL,
                        vecsAlias.c_str(),
                        NULL,
                        &pStore);
    }
    BAIL_ON_ERROR(dwError);

    dwError =  VecsAddEntryA(
                        pStore,
                        CERT_ENTRY_TYPE_PRIVATE_KEY,
                        vecsAlias.c_str(),
                        pszCert,
                        pszPrivateKey,
                        NULL, /* password */
                        1);   /* auto refresh */
    if (dwError != 0)
    {
        printf("Warning : %d, Adding cert to VECS Store Failed.", dwError);
        dwError = 0;
    }

#endif

error :
    if(pszDomainName)
    {
        VmAfdFreeString(pszDomainName);
    }

    VMCA_SAFE_FREE_STRINGA(pszMachineID);
    VMCA_SAFE_FREE_STRINGA(pszOrgUnit);

#ifndef __NO_AFD__
    if (pStore)
    {
        VecsCloseCertStore(pStore);
    }
#endif
    if( pszCert != NULL) {
        VMCA_SAFE_FREE_STRINGA(pszCert);
    }

    if (pszPrivateKey != NULL) {
        VMCA_SAFE_FREE_STRINGA(pszPrivateKey);
    }

    return dwError;
}

DWORD
HandleWaitVMCA()
{
    DWORD dwError = 0;
    int secondsToSleep = 0;
    time_t  endTime, currentTime;
    PVMCA_CERTIFICATE pCert = NULL;
    PVMCA_SERVER_CONTEXT hServer = NULL;

    if ( argWait <= 0 )
    {
        dwError = VMCA_ARGUMENT_ERROR;
        BAIL_ON_ERROR(dwError);
    }

    time(&currentTime);

    endTime = currentTime + ( argWait * 60 );
    while ( currentTime < endTime ) {

        // Call into VMCA Server to get Version Number
        dwError = _HandleOpenServer(&hServer);

        if (dwError == ERROR_SUCCESS)
        {
            dwError = VMCAGetRootCACertificateHA(
                hServer,
                (PCSTR) argServerName.c_str(),
                &pCert
                );

            VMCACloseServer(hServer);

            if ( dwError == 0 )
            {
                // means server is up and working
                break;
            }
        }
        sleep(GetSleepTime(10)); // Sleep for 10 seconds
        printf(".");
        fflush(stdout);
        time(&currentTime);
    }

    if ((currentTime >= endTime) &&
        (dwError != 0))
    {
        dwError = VMCA_ERROR_TIME_OUT;
        BAIL_ON_ERROR(dwError);
    }

error:
    if (pCert != NULL ) {
        VMCAFreeCertificate(pCert);
    }

    return dwError;

}

DWORD
HandleWaitVMDIR()
{
  DWORD dwError = 0;
  int secondsToSleep = 0;
  time_t  endTime, currentTime;

  if ( argWait <= 0 )
  {
    dwError = VMCA_ARGUMENT_ERROR;
    BAIL_ON_ERROR(dwError);
  }

  time(&currentTime);

  endTime = currentTime + ( argWait * 60 );
  while ( currentTime < endTime ) {

// Call into VMDIR Server to make sure that it is up and running.

    dwError =  VMCACheckLdapConnection(
                   (PSTR) argServerName.c_str(),argPort);
    if ( dwError == 0 )
    {
      // means server is up and working
      break;
    }
    sleep(GetSleepTime(10)); // Sleep for 10 seconds
    printf(".");
    fflush(stdout);
    time(&currentTime);
  }

  if ((currentTime >= endTime) &&
      (dwError != 0))
  {
    dwError = VMCA_ERROR_TIME_OUT;
    BAIL_ON_ERROR(dwError);
  }

error:
  return dwError;
}

DWORD
HandleInitVMCA()
{

  DWORD dwError = 0;
  int secondsToSleep = 0;
  time_t  endTime, currentTime;
  PSTR pVersionString = NULL;
  PVMCA_SERVER_CONTEXT hServer = NULL;

  if ( argWait <= 0 )
  {
    dwError = VMCA_ARGUMENT_ERROR;
    BAIL_ON_ERROR(dwError);
  }

  time(&currentTime);

  endTime = currentTime + ( argWait * 60 );
  while ( currentTime < endTime ) {

 // Call into VMCA Server to get Version Number

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    dwError = VMCAGetServerVersionHA(
                  hServer,
                  (PCSTR) argServerName.c_str(),
                  &pVersionString
              );

    VMCACloseServer(hServer);
    hServer = NULL;

    if ( dwError == 0 )
    {
      // means server is up and working
      break;
    }
    sleep(GetSleepTime(10)); // Sleep for 10 seconds
    printf(".");
    fflush(stdout);
    time(&currentTime);
  }

  if ((currentTime >= endTime) &&
      (dwError != 0))
  {
    dwError = VMCA_ERROR_TIME_OUT;
    BAIL_ON_ERROR(dwError);
  }

error:
  if (pVersionString != NULL ) {
    VMCAFreeStringA(pVersionString);
  }

  return dwError;

}

DWORD
HandleStatusCert()
{

    DWORD dwError = 0;
    PVMCA_CERTIFICATE pCert = NULL;
    DWORD dwStatus = VMCA_CERTIFICATE_ALL;
    PVMCA_SERVER_CONTEXT hServer = NULL;
//
// Step 1: Read the Certificate from File
//
    dwError = VMCAReadCertificateFromFile(
                  (LPSTR)argCert.c_str(),
                  &pCert);
    BAIL_ON_ERROR(dwError);
//
// Step 2: Call into Server to verify  the Status of the Certificate
//

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    dwError = VMCAVerifyCertificateHA(
                   hServer,
                  (PCSTR) argServerName.c_str(),
                  (PSTR) pCert,
                  &dwStatus);
    BAIL_ON_ERROR(dwError);

    switch (dwStatus)
    {
        case VMCA_CERTIFICATE_ACTIVE:
          std::cout << "Certificate : ACTIVE" << std::endl;
          break;

        case VMCA_CERTIFICATE_REVOKED:
          std::cout << "Certificate : REVOKED" << std::endl;
          break;

        case VMCA_CERTIFICATE_EXPIRED:
          std::cout << "Certificate : EXPIRED" << std::endl;
          break;

        default:
          std::cout << "Certificate : INVALID_STATE" << std::endl;
    }

error :
    if (hServer)
    {
        VMCACloseServer(hServer);
    }

    VMCAFreeCertificate(pCert);
    return dwError;
}

DWORD
HandleVecsEnum()
{
    DWORD dwError = 0;

    dwError = VMCA_NOT_IMPLEMENTED;

    return dwError;
}

DWORD
HandleGetCRL()
{
  DWORD dwError = 0;
  PVMCA_SERVER_CONTEXT hServer = NULL;

  dwError = _HandleOpenServer(&hServer);
  BAIL_ON_ERROR(dwError);

  dwError = VMCAGetCRLHA(
    hServer,
    (PCSTR)argServerName.c_str(),
    (PSTR) argCurrCrl.c_str(),
    (PSTR) argCrl.c_str()
    );

error:
  if (hServer)
  {
      VMCACloseServer(hServer);
  }
  return dwError;
}

DWORD
HandleGenCRL()
{
  DWORD dwError = 0;
  PVMCA_SERVER_CONTEXT hServer = NULL;

  dwError = _HandleOpenServer(&hServer);
  BAIL_ON_ERROR(dwError);

  dwError = VMCAReGenCRLHA(
    hServer,
    (PCSTR)argServerName.c_str()
    );

error:
  if (hServer)
  {
      VMCACloseServer(hServer);
  }
  return dwError;
}

DWORD
HandleCRLInfo()
{
  DWORD dwError = 0;
  time_t dwLastUpdate = 0;
  time_t dwNextUpdate = 0;
  DWORD dwCrlNumber = 0;
  time_t t = 0;

  dwError =  VMCAGetCRLInfo2(
              (PSTR) argCrl.c_str(),
              &dwLastUpdate,
              &dwNextUpdate,
              &dwCrlNumber);
  BAIL_ON_ERROR(dwError);
  t = (time_t) dwLastUpdate;
  std::cout  << "CRL Name    : " << argCrl << std::endl;
  std::cout  << "Last Update : "  <<  asctime(gmtime(&t));
  t = (time_t) dwNextUpdate;
  std::cout  << "Next Update : "  <<  asctime(gmtime(&t));
  std::cout  << "CRL Number  : " << dwCrlNumber << std::endl;

error :
  return dwError;
}

DWORD
HandlePrintError()
{

    DWORD dwError = 0;
    PSTR pszShortErrMessage = NULL;
    PSTR pszLongMessage = NULL;
    dwError  = VMCAGetShortError(argErr, &pszShortErrMessage);
    BAIL_ON_ERROR(dwError);
    std::cout << "Short Error : " << pszShortErrMessage << std::endl;

    dwError = VMCAGetErrorString(argErr, &pszLongMessage);
    BAIL_ON_ERROR(dwError);
    std::cout << pszLongMessage << std::endl;

error :
    VMCA_SAFE_FREE_STRINGA(pszShortErrMessage);
    VMCA_SAFE_FREE_STRINGA(pszLongMessage);
    return dwError;
}

DWORD
HandlePrintCRL()
{
  DWORD dwError = 0;
  PSTR pszCRLString = NULL;
  dwError = VMCAPrintCRL((PSTR)argCrl.c_str(), &pszCRLString);
  BAIL_ON_ERROR(dwError);

  std::cout << "CRL Info : " << std::endl << pszCRLString <<std::endl;

error :
  VMCA_SAFE_FREE_STRINGA(pszCRLString);
  return dwError;
}

DWORD
HandlePublishRoots()
{
  DWORD dwError = 0;
  PVMCA_SERVER_CONTEXT hServer = NULL;

  dwError = _HandleOpenServer(&hServer);
  BAIL_ON_ERROR(dwError);

  dwError = VMCAPublishRootCertsHA(hServer, (LPSTR) argServerName.c_str());
  BAIL_ON_ERROR(dwError);

error:
  if (hServer)
  {
      VMCACloseServer(hServer);
  }
  return dwError;
}

DWORD
HandleUpdateSchema()
{
    DWORD dwError = 0;
    //TODO: Implement schema update. Placeholder for upgrade tests
    return dwError;
}

DWORD
HandleGenSelfCert()
{
    DWORD dwError = 0;

    PVMCA_KEY pPrivateKey = NULL;
    PVMCA_KEY pPublicKey = NULL;
    PVMCA_PKCS_10_REQ_DATAA pCertReqData = NULL;
    PVMCA_CERTIFICATE pCertificate = NULL;
    unsigned long dwMask = 0;
    time_t timeNow = 0, timeExpire = 0;
    time_t timeUtcNow = 0, timeUtcExpire = 0;

    dwError = VMCACreatePrivateKey(
                    NULL,
                    CERTOOL_PRIVATE_KEY_LENGTH,
                    &pPrivateKey,
                    &pPublicKey
                    );
    BAIL_ON_ERROR(dwError);

    dwError = VMCAAllocatePKCS10DataA(&pCertReqData);
    BAIL_ON_ERROR(dwError);

    dwError = VMCAInitPKCS10DataWithDCA(
                    cfgName.c_str(),
                    cfgDomainComponent.c_str(),
                    cfgOrganization.c_str(),
                    cfgOrgUnit.c_str(),
                    cfgState.c_str(),
                    cfgCountry.c_str(),
                    cfgEmail.c_str(),
                    cfgIPAddress.c_str(),
                    pCertReqData
                    );
    BAIL_ON_ERROR(dwError);

    if(cfgLocality.length() > 0)
    {
        dwError = VMCASetCertValueA(
                        VMCA_OID_LOCALITY,
                        pCertReqData,
                        (PSTR)cfgLocality.c_str()
                        );
        BAIL_ON_ERROR(dwError);
    }

    if(cfgHostName.length() > 0)
    {
        dwError = VMCASetCertValueA(
                        VMCA_OID_DNS,
                        pCertReqData,
                        (PSTR)cfgHostName.c_str()
                        );
        BAIL_ON_ERROR(dwError);
    }

    VMCASetBit(&dwMask, VMCA_KEY_CERT_SIGN);
    VMCASetBit(&dwMask, VMCA_KEY_CRL_SIGN);

    VMCASetKeyUsageConstraintsA(
                    pCertReqData,
                    dwMask
                    );

    time(&timeNow);
    timeNow -= (argPredates * 60);
    timeExpire = timeNow + VMCA_DEFAULT_CA_CERT_VALIDITY;

    VMCAGetGMTime(timeNow, &timeUtcNow);
    VMCAGetGMTime(timeExpire, &timeUtcExpire);

    dwError =  VMCACreateSelfSignedCertificateA(
                     pCertReqData,
                     pPrivateKey,
                     NULL,
                     timeUtcNow,
                     timeUtcExpire,
                     &pCertificate
                     );
    BAIL_ON_ERROR(dwError);

    dwError =  VMCAWriteCertificateToFile(
                    (LPSTR) argOutCert.c_str(),
                    pCertificate
                    );
    BAIL_ON_ERROR(dwError);

    dwError =  VMCAWritePrivateKeyToFile(
                    (LPSTR) argOutPrivateKey.c_str(),
                    pPrivateKey,
                    NULL,
                    NULL
                    );
    BAIL_ON_ERROR(dwError);

error:
    VMCAFreeKey(pPrivateKey);
    VMCAFreeKey(pPublicKey);
    VMCAFreePKCS10DataA(pCertReqData);
    VMCAFreeCertificate(pCertificate);

    return dwError;
}

DWORD
HandleGenCSRFromCert()
{
    DWORD dwError = 0;

    EVP_PKEY *pPrivateKey = NULL;
    X509_REQ *pCertReq = NULL;
    X509 *pCertificate = NULL;

    dwError = VMCAReadX509FromFile(
                        (LPSTR) argCert.c_str(),
                        &pCertificate
                        );
    BAIL_ON_ERROR (dwError);

    dwError = VMCAReadPKEYFromFile(
                        (LPSTR) argPrivateKey.c_str(),
                        NULL,
                        &pPrivateKey
                        );
    BAIL_ON_ERROR (dwError);

    dwError = VMCAGetCSRFromCert(
                          pCertificate,
                          pPrivateKey,
                          &pCertReq
                          );
    BAIL_ON_ERROR (dwError);

    dwError = VMCACSRToFile(
                       pCertReq,
                       (LPSTR) argCsr.c_str()
                       );
    BAIL_ON_ERROR (dwError);

cleanup:
    X509_free(pCertificate);
    X509_REQ_free(pCertReq);
    EVP_PKEY_free(pPrivateKey);
    return dwError;

error:
    goto cleanup;

}

DWORD
HandleSetServerOption()
{
    DWORD   dwError = 0;
    unsigned int    dwOption = 0;
    PVMCA_SERVER_CONTEXT    hServer = NULL;

    if (std::strcmp(argOption.c_str(), VMCA_OPTION_MULTIPLE_SAN) == 0) {
        dwOption = VMCA_SERVER_OPT_ALLOW_MULTIPLE_SAN;
    }
    else
    {
        std::cerr << "Unrecognizable server option: " << argOption << std::endl;
        dwError = VMCA_ARGUMENT_ERROR;
        BAIL_ON_ERROR(dwError);
    }

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    // Call into VMCA Server to set server option
    dwError =  VMCASetServerOptionHA(
            hServer, (PCSTR)argServerName.c_str(), dwOption);
    BAIL_ON_ERROR(dwError);

error:
    if (hServer)
    {
        VMCACloseServer(hServer);
    }
    return dwError;
}

DWORD
HandleUnsetServerOption()
{
    DWORD   dwError = 0;
    unsigned int    dwOption = 0;
    PVMCA_SERVER_CONTEXT    hServer = NULL;

    if (std::strcmp(argOption.c_str(), VMCA_OPTION_MULTIPLE_SAN) == 0) {
        dwOption = VMCA_SERVER_OPT_ALLOW_MULTIPLE_SAN;
    }
    else
    {
        std::cerr << "Unrecognizable server option: " << argOption << std::endl;
        dwError = VMCA_ARGUMENT_ERROR;
        BAIL_ON_ERROR(dwError);
    }

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    // Call into VMCA Server to unset server option
    dwError =  VMCAUnsetServerOptionHA(
            hServer, (PCSTR)argServerName.c_str(), dwOption);
    BAIL_ON_ERROR(dwError);

error:
    if (hServer)
    {
        VMCACloseServer(hServer);
    }
    return dwError;
}

DWORD
HandleGetServerOption()
{
    DWORD   dwError = 0;
    DWORD   i = 0;
    unsigned int    dwOption = 0;
    PVMCA_SERVER_CONTEXT    hServer = NULL;

    dwError = _HandleOpenServer(&hServer);
    BAIL_ON_ERROR(dwError);

    // Call into VMCA Server to get server option
    dwError =  VMCAGetServerOptionHA(
            hServer, (PCSTR)argServerName.c_str(), &dwOption);
    BAIL_ON_ERROR(dwError);

    // Print enabled options
    for (i = 1; i < VMCA_SERVER_OPT_COUNT; i <<= 1)
    {
        if (dwOption & i)
        {
            switch (i)
            {
            case VMCA_SERVER_OPT_ALLOW_MULTIPLE_SAN:
                std::cout << VMCA_OPTION_MULTIPLE_SAN << std::endl;
                break;

            default:
                break;
            }
        }
    }

error:
    if (hServer)
    {
        VMCACloseServer(hServer);
    }
    return dwError;
}


text:
//
// execution/occupancy.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_EXECUTION_OCCUPANCY_HPP
#define BOOST_ASIO_EXECUTION_OCCUPANCY_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/execution/executor.hpp>
#include <boost/asio/execution/scheduler.hpp>
#include <boost/asio/execution/sender.hpp>
#include <boost/asio/is_applicable_property.hpp>
#include <boost/asio/traits/query_static_constexpr_member.hpp>
#include <boost/asio/traits/static_query.hpp>

#include <boost/asio/detail/push_options.hpp>

namespace boost {
namespace asio {

#if defined(GENERATING_DOCUMENTATION)

namespace execution {

/// A property that gives an estimate of the number of execution agents that
/// should occupy the associated execution context.
struct occupancy_t
{
  /// The occupancy_t property applies to executors, senders, and schedulers.
  template <typename T>
  static constexpr bool is_applicable_property_v =
    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;

  /// The occupancy_t property cannot be required.
  static constexpr bool is_requirable = false;

  /// The occupancy_t property cannot be preferred.
  static constexpr bool is_preferable = false;

  /// The type returned by queries against an @c any_executor.
  typedef std::size_t polymorphic_query_result_type;
};

/// A special value used for accessing the occupancy_t property.
constexpr occupancy_t occupancy;

} // namespace execution

#else // defined(GENERATING_DOCUMENTATION)

namespace execution {
namespace detail {

template <int I = 0>
struct occupancy_t
{
#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  template <typename T>
  BOOST_ASIO_STATIC_CONSTEXPR(bool,
    is_applicable_property_v = is_executor<T>::value
      || is_sender<T>::value || is_scheduler<T>::value);
#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)

  BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
  BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  typedef std::size_t polymorphic_query_result_type;

  BOOST_ASIO_CONSTEXPR occupancy_t()
  {
  }

#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  template <typename T>
  static BOOST_ASIO_CONSTEXPR
  typename traits::query_static_constexpr_member<T, occupancy_t>::result_type
  static_query()
    BOOST_ASIO_NOEXCEPT_IF((
      traits::query_static_constexpr_member<T, occupancy_t>::is_noexcept))
  {
    return traits::query_static_constexpr_member<T, occupancy_t>::value();
  }

  template <typename E, typename T = decltype(occupancy_t::static_query<E>())>
  static BOOST_ASIO_CONSTEXPR const T static_query_v
    = occupancy_t::static_query<E>();
#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
       //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)

#if !defined(BOOST_ASIO_HAS_CONSTEXPR)
  static const occupancy_t instance;
#endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
};

#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
template <int I> template <typename E, typename T>
const T occupancy_t<I>::static_query_v;
#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
       //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)

#if !defined(BOOST_ASIO_HAS_CONSTEXPR)
template <int I>
const occupancy_t<I> occupancy_t<I>::instance;
#endif

} // namespace detail

typedef detail::occupancy_t<> occupancy_t;

#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
constexpr occupancy_t occupancy;
#else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
namespace { static const occupancy_t& occupancy = occupancy_t::instance; }
#endif

} // namespace execution

#if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)

template <typename T>
struct is_applicable_property<T, execution::occupancy_t>
  : integral_constant<bool,
      execution::is_executor<T>::value
        || execution::is_sender<T>::value
        || execution::is_scheduler<T>::value>
{
};

#endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)

namespace traits {

#if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)

template <typename T>
struct static_query<T, execution::occupancy_t,
  typename enable_if<
    traits::query_static_constexpr_member<T,
      execution::occupancy_t>::is_valid
  >::type>
{
  BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);

  typedef typename traits::query_static_constexpr_member<T,
    execution::occupancy_t>::result_type result_type;

  static BOOST_ASIO_CONSTEXPR result_type value()
  {
    return traits::query_static_constexpr_member<T,
      execution::occupancy_t>::value();
  }
};

#endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
       //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)

} // namespace traits

#endif // defined(GENERATING_DOCUMENTATION)

} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_EXECUTION_OCCUPANCY_HPP

ext: hpp

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
//  Copyright (c) 2005-2007 Andre Merzky (andre@merzky.net)
//  Copyright (c) 2005-2009 Hartmut Kaiser
//  Copyright (c) 2005 Michel Zandstra [michelzandstra@gmail.com]
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  job LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef CONTEXT_BASE_HPP
#define CONTEXT_BASE_HPP

#include <map>
#include <vector>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>

#include <saga/saga/context.hpp>
#include <saga/saga/exception.hpp>
#include <saga/saga/adaptors/attribute.hpp>
#include <saga/impl/exception.hpp>

#include <saga/impl/config.hpp>
#include <saga/impl/context_cpi.hpp>
#include <saga/impl/engine/attribute.hpp>
#include <saga/impl/engine/object.hpp>
#include <saga/impl/engine/proxy.hpp>

///////////////////////////////////////////////////////////////////////////////
namespace saga { namespace impl
{
    /**
     * Context_base: base class for all context classes
     */
    class context
      : public saga::impl::proxy,
        public saga::impl::attribute
    {
    private:
        typedef v1_0::context_cpi context_cpi;
        typedef v1_0::preference_type preference_type;
        typedef saga::impl::attribute attribute_base;

        explicit context (attribute const& rhs_attr);
        void init();

    public:
        /** constructor, defines context type */
        explicit context();

        // saga::object interface
        saga::object clone() const
        {
            return saga::context(new saga::impl::context(
                static_cast<attribute_base const&>(*this)));
        }

        bool is_equal (saga::impl::object *rhs) const
        {
            return static_cast<attribute_base const&>(*this).is_equal(
                *(rhs->get_attributes()));
        }

        // API function
        SAGA_CALL_IMPL_DECL_0(set_defaults)

        saga::impl::attribute* get_attributes() { return this; }
        saga::impl::attribute const* get_attributes() const { return this; }

        saga::impl::proxy* get_proxy() { return this; }
        saga::impl::proxy const* get_proxy() const { return this; }

    }; // class context_base

}} // namespace saga::impl

#endif // CONTEXT_BASE_HPP

max_stars_repo_name: saga-project/saga-cpp

max_issues_repo_name: saga-project/saga-cpp

max_forks_repo_name: saga-project/saga-cpp


text:
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_CONTAINER_MUTEX_HPP
#define BOOST_CONTAINER_MUTEX_HPP

#ifndef BOOST_CONFIG_HPP
#  include <boost/config.hpp>
#endif

#if defined(BOOST_HAS_PRAGMA_ONCE)
#  pragma once
#endif

//#define BOOST_CONTAINER_NO_MT
//#define BOOST_CONTAINER_NO_SPINLOCKS

#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>

// Extremely Light-Weight wrapper classes for OS thread synchronization

#define BOOST_MUTEX_HELPER_NONE         0
#define BOOST_MUTEX_HELPER_WIN32        1
#define BOOST_MUTEX_HELPER_PTHREAD      2
#define BOOST_MUTEX_HELPER_SPINLOCKS    3

#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
# define BOOST_NO_MT
#endif

#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
  // No multithreading -> make locks into no-ops
  #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
#else
   //Taken from dlmalloc
   #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) &&                           \
         ((defined(__GNUC__) &&                                            \
         ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) ||      \
         defined(__i386__) || defined(__x86_64__))) ||                     \
      (defined(_MSC_VER) && _MSC_VER>=1310))
      #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
   #endif

   #if defined(BOOST_WINDOWS)
      #include <windows.h>
      #ifndef BOOST_MUTEX_HELPER
         #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
      #endif
   #elif defined(BOOST_HAS_UNISTD_H)
      #include <unistd.h>
      #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
         #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
      #endif
   #endif
#endif

#ifndef BOOST_MUTEX_HELPER
  #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
#endif

#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
   //...
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
   #if defined(_MSC_VER)
      #ifndef _M_AMD64
         /* These are already defined on AMD64 builds */
         #ifdef __cplusplus
            extern "C" {
         #endif /* __cplusplus */
            long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
            long __cdecl _InterlockedExchange(long volatile *Target, long Value);
         #ifdef __cplusplus
            }
         #endif /* __cplusplus */
      #endif /* _M_AMD64 */
      #pragma intrinsic (_InterlockedCompareExchange)
      #pragma intrinsic (_InterlockedExchange)
      #define interlockedcompareexchange _InterlockedCompareExchange
      #define interlockedexchange        _InterlockedExchange
   #elif defined(WIN32) && defined(__GNUC__)
      #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
      #define interlockedexchange                 __sync_lock_test_and_set
   #endif /* Win32 */

   /* First, define CAS_LOCK and CLEAR_LOCK on ints */
   /* Note CAS_LOCK defined to return 0 on success */

   #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
      #define BOOST_CONTAINER_CAS_LOCK(sl)     __sync_lock_test_and_set(sl, 1)
      #define BOOST_CONTAINER_CLEAR_LOCK(sl)   __sync_lock_release(sl)

   #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
      /* Custom spin locks for older gcc on x86 */
      static inline int boost_container_x86_cas_lock(int *sl) {
         int ret;
         int val = 1;
         int cmp = 0;
         __asm__ __volatile__  ("lock; cmpxchgl %1, %2"
                                 : "=a" (ret)
                                 : "r" (val), "m" (*(sl)), "0"(cmp)
                                 : "memory", "cc");
         return ret;
      }

      static inline void boost_container_x86_clear_lock(int* sl) {
         assert(*sl != 0);
         int prev = 0;
         int ret;
         __asm__ __volatile__ ("lock; xchgl %0, %1"
                                 : "=r" (ret)
                                 : "m" (*(sl)), "0"(prev)
                                 : "memory");
      }

      #define BOOST_CONTAINER_CAS_LOCK(sl)     boost_container_x86_cas_lock(sl)
      #define BOOST_CONTAINER_CLEAR_LOCK(sl)   boost_container_x86_clear_lock(sl)

   #else /* Win32 MSC */
      #define BOOST_CONTAINER_CAS_LOCK(sl)     interlockedexchange((long volatile*)sl, (long)1)
      #define BOOST_CONTAINER_CLEAR_LOCK(sl)   interlockedexchange((long volatile*)sl, (long)0)
   #endif

   /* How to yield for a spin lock */
   #define SPINS_PER_YIELD       63
   #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
      #define SLEEP_EX_DURATION     50 /* delay for yield/sleep */
      #define SPIN_LOCK_YIELD  SleepEx(SLEEP_EX_DURATION, FALSE)
   #elif defined (__SVR4) && defined (__sun) /* solaris */
      #include <thread.h>
      #define SPIN_LOCK_YIELD   thr_yield();
   #elif !defined(LACKS_SCHED_H)
      #include <sched.h>
      #define SPIN_LOCK_YIELD   sched_yield();
   #else
      #define SPIN_LOCK_YIELD
   #endif /* ... yield ... */

   #define BOOST_CONTAINER_SPINS_PER_YIELD       63
   inline int boost_interprocess_spin_acquire_lock(int *sl) {
      int spins = 0;
      while (*(volatile int *)sl != 0 ||
         BOOST_CONTAINER_CAS_LOCK(sl)) {
         if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
            SPIN_LOCK_YIELD;
         }
      }
      return 0;
   }
   #define BOOST_CONTAINER_MLOCK_T               int
   #define BOOST_CONTAINER_TRY_LOCK(sl)          !BOOST_CONTAINER_CAS_LOCK(sl)
   #define BOOST_CONTAINER_RELEASE_LOCK(sl)      BOOST_CONTAINER_CLEAR_LOCK(sl)
   #define BOOST_CONTAINER_ACQUIRE_LOCK(sl)      (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
   #define BOOST_MOVE_INITIAL_LOCK(sl)      (*sl = 0)
   #define BOOST_CONTAINER_DESTROY_LOCK(sl)      (0)
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
   //
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
   #include <pthread.h>
#endif

namespace boost {
namespace container {
namespace container_detail {

#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
   class null_mutex
   {
   private:
      null_mutex(const null_mutex &);
      void operator=(const null_mutex &);

   public:
      null_mutex() { }

      static void lock() { }
      static void unlock() { }
   };

  typedef null_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS

   class spin_mutex
   {
   private:
      BOOST_CONTAINER_MLOCK_T sl;
      spin_mutex(const spin_mutex &);
      void operator=(const spin_mutex &);

   public:
      spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }

      void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
      void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
   };
  typedef spin_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
   class mutex
   {
   private:
      CRITICAL_SECTION mtx;

      mutex(const mutex &);
      void operator=(const mutex &);

   public:
      mutex()
      { InitializeCriticalSection(&mtx); }

      ~mutex()
      { DeleteCriticalSection(&mtx); }

      void lock()
      { EnterCriticalSection(&mtx); }

      void unlock()
      { LeaveCriticalSection(&mtx); }
   };

  typedef mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
   class mutex
   {
   private:
      pthread_mutex_t mtx;

      mutex(const mutex &);
      void operator=(const mutex &);

   public:
      mutex()
      { pthread_mutex_init(&mtx, 0); }

      ~mutex()
      { pthread_mutex_destroy(&mtx); }

      void lock()
      { pthread_mutex_lock(&mtx); }

      void unlock()
      { pthread_mutex_unlock(&mtx); }
   };

  typedef mutex default_mutex;
#endif

template<class Mutex>
class scoped_lock
{
   public:
   scoped_lock(Mutex &m)
      :  m_(m)
   { m_.lock(); }
   ~scoped_lock()
   { m_.unlock(); }

   private:
   Mutex &m_;
};

} // namespace container_detail
} // namespace container
} // namespace boost

#undef BOOST_MUTEX_HELPER_WIN32
#undef BOOST_MUTEX_HELPER_PTHREAD
#undef BOOST_MUTEX_HELPER_NONE
#undef BOOST_MUTEX_HELPER
#undef BOOST_MUTEX_HELPER_SPINLOCKS

#include <boost/container/detail/config_end.hpp>

#endif

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
#include <boost/test/unit_test.hpp>

#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/ref.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

#include <iostream>
#include <fstream>
#include <map>
#include <deque>
#include <algorithm>
#include <ir/index_manager/index/FieldIndexer.h>
#include <ir/index_manager/store/FSIndexInput.h>

using namespace std;
using namespace boost;

using namespace izenelib::ir::indexmanager;

namespace bfs = boost::filesystem;

std::map<std::string, unsigned int> propertyMap;
boost::uniform_int<> termDistribution(0xFFFF, 0x7FFFFFFF) ;
boost::mt19937 engine ;
boost::variate_generator<boost::mt19937, boost::uniform_int<> > termrandom (engine, termDistribution);
boost::uniform_int<> offsetDistribution(0, 2000);
boost::variate_generator<boost::mt19937, boost::uniform_int<> > offsetrandom (engine, offsetDistribution);

std::string file;

izenelib::am::IzeneSort<uint32_t, uint8_t, true,SortIO<FieldIndexIO> >* sorter = NULL;

uint8_t convert(char* data, uint32_t termId, uint32_t docId, uint32_t offset)
{
    char* pData = data;
    memcpy(pData, &(termId), sizeof(termId));
    pData += sizeof(uint32_t);
    FieldIndexIO::addVInt(pData, docId);
    FieldIndexIO::addVInt(pData, offset);
    return pData - data;
}

void buildup()
{
    bfs::path path(bfs::path(".") /"Content.tmp");
    file = path.string();
    sorter = new izenelib::am::IzeneSort<uint32_t, uint8_t, true,SortIO<FieldIndexIO> >
      (file.c_str(), 10000000);

        char data[12];
        uint8_t len = 12;
    for(size_t i = 1; i <= 100; ++i)
    {
        for (size_t j = 0; j < 10; ++j)
        {
            len = convert(data,termrandom(),i,offsetrandom());
            sorter->add_data(len,data);
        }
    }
    sorter->sort();
}

void cleanup()
{
    sorter->clear_files();
    bfs::path indexPath(bfs::path(".") /"Content.tmp");
    boost::filesystem::remove_all(indexPath);
    if(sorter) delete sorter;
}

BOOST_AUTO_TEST_SUITE( t_index_sort )

BOOST_AUTO_TEST_CASE(sort)
{
    buildup();

    IndexInput* pSortedInput = new FSIndexInput(file.c_str());
    std::deque<uint32_t>	 terms;
    std::deque<std::deque<uint32_t> > termDocs;
    uint64_t c = pSortedInput->readLongBySmallEndian();
    uint32_t tid = 0;
    uint32_t lastTid = 0;
    uint32_t lastDoc = 0;
    uint32_t lastOffset = 0;
    //std::deque<uint32_t> termDoc;
    cout<<"count "<<c<<endl;
    for (uint64_t i = 0; i < c; ++i)
    {
        uint8_t len = pSortedInput->readByte();
        BOOST_CHECK(len == 12);
        tid = pSortedInput->readIntBySmallEndian();
        uint32_t docId = pSortedInput->readVInt();
        uint32_t offset = pSortedInput->readVInt();
        //termDoc.push_back(docId);
        if(tid != lastTid && lastTid != 0)
        {
            terms.push_back(tid);
            //termDocs.push_back(termDoc);
            //termDoc.clear();
        }
        //BOOST_CHECK(tid >= lastTid);
        lastTid = tid;
        lastDoc = docId;
        lastOffset = offset;
    }
    delete pSortedInput;
    cout<<"overall "<<terms.size()<<" terms"<<endl;
    std::deque<uint32_t> sortedTerms = terms;
    std::sort(sortedTerms.begin(), sortedTerms.end());
    BOOST_CHECK(sortedTerms.size() == terms.size());
    for(size_t i = 0; i < terms.size(); ++i)
        BOOST_CHECK(sortedTerms[i] == terms[i]);

    cleanup();
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: izenecloud/izenelib

max_issues_repo_name: izenecloud/izenelib

max_forks_repo_name: izenecloud/izenelib


text:
//
//  fiberize.hpp
//  fibio
//
//  Created by Chen Xu on 14-3-8.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#ifndef fibio_fiberize_hpp
#define fibio_fiberize_hpp

#include <type_traits>
#include <memory>
#include <iostream>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/asio/windows/stream_handle.hpp>
#include <fibio/fibers/fiber.hpp>
#include <fibio/stream/streambuf.hpp>

/// Define this to stop using fiberized std stream
//#define FIBIO_DONT_FIBERIZE_STD_STREAM

/// Define this to stop using default main implementation
//#define FIBIO_DONT_USE_DEFAULT_MAIN

// Doesn't work under Windows
#if defined(_WIN32)
#define FIBIO_DONT_FIBERIZE_STD_STREAM
#endif

namespace fibio {
namespace fibers {
namespace detail {

#if !defined(FIBIO_DONT_FIBERIZE_STD_STREAM)

template <typename Stream,
          typename Desc,
          typename CharT = char,
          typename Traits = std::char_traits<CharT>>
struct guard
{
    typedef typename Desc::native_handle_type native_handle_type;
    typedef stream::streambuf<Desc> sbuf_t;
    typedef std::unique_ptr<sbuf_t> sbuf_ptr_t;

    guard(Stream& s, native_handle_type h, bool unbuffered = false)
    : new_buf_(new sbuf_t(this_fiber::detail::get_io_service())), stream_(s)
    {
        old_buf_ = stream_.rdbuf(new_buf_.get());
        new_buf_->assign(h);
        // Don't sync with stdio, it doesn't work anyway
        stream_.sync_with_stdio(false);
        // Set to unbuffered if needed
        if (unbuffered) stream_.rdbuf()->pubsetbuf(0, 0);
    }

    ~guard()
    {
        flush(stream_);
#if BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
        new_buf_->release();
#endif
        stream_.rdbuf(old_buf_);
    }

    // HACK: only ostream can be flushed
    void flush(std::basic_ostream<CharT, Traits>& s) { s.flush(); }

    void flush(std::basic_istream<CharT, Traits>& s) {}

    sbuf_ptr_t new_buf_;
    Stream& stream_;
    std::streambuf* old_buf_ = 0;
};

#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
// POSIX platform
typedef boost::asio::posix::stream_descriptor std_handle_type;
typedef std_handle_type::native_handle_type native_handle_type;

native_handle_type std_in_handle()
{
    return 0;
}

native_handle_type std_out_handle()
{
    return 1;
}

native_handle_type std_err_handle()
{
    return 2;
}

#elif defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
// Windows platform
typedef boost::asio::windows::stream_handle std_handle_type;
typedef std_handle_type::native_handle_type native_handle_type;
native_handle_type std_in_handle()
{
    return ::GetStdHandle(STD_INPUT_HANDLE);
}
native_handle_type std_out_handle()
{
    return ::GetStdHandle(STD_OUTPUT_HANDLE);
}
native_handle_type std_err_handle()
{
    return ::GetStdHandle(STD_ERROR_HANDLE);
}
#else
#error("Unsupported platform")
#endif

struct std_stream_guard
{
    guard<std::istream, std_handle_type> cin_guard_{std::cin, std_in_handle()};
    guard<std::ostream, std_handle_type> cout_guard_{std::cout, std_out_handle()};
    guard<std::ostream, std_handle_type> cerr_guard_{std::cerr, std_err_handle(), true};
};

#else // !defined(FIBIO_DONT_FIBERIZE_STD_STREAM), No std stream guard, do nothing
struct std_stream_guard
{
};
#endif // !defined(FIBIO_DONT_FIBERIZE_STD_STREAM)

// HACK: C++ forbids variable with `void` type as it is always incomplete
template <typename T>
struct non_void
{
    typedef T type;

    template <typename Fn, typename... Args>
    static void run(type& t, Fn&& fn, Args&&... args)
    {
        t = std::forward<Fn>(fn)(std::forward<Args>(args)...);
    }
};

template <>
struct non_void<void>
{
    typedef int type;

    template <typename Fn, typename... Args>
    static void run(type& t, Fn&& fn, Args&&... args)
    {
        t = 0;
        std::forward<Fn>(fn)(std::forward<Args>(args)...);
    }
};

} // End of namespace detail

/**
 * Start the scheduler and create the first fiber in it
 *
 * @param sched the scheduler to run the fiber
 * @param fn the entry point of the fiber
 * @param args the arguments for the fiber
 */
// NOTE: I cannot make this specialization work in VC2015, gave up and changed the name...
template <typename Fn, typename... Args>
auto fiberize_with_sched(fibio::scheduler&& sched, Fn&& fn, Args&&... args) ->
    typename std::result_of<Fn(Args...)>::type
{
    typedef typename std::result_of<Fn(Args...)>::type result_type;
    typedef detail::non_void<result_type> non_void_result;
    typename non_void_result::type ret{};
    try {
        sched.start();
        fibio::fiber f(sched,
                       [&]() {
                           detail::std_stream_guard guard;
                           // Disable unused variable warning
                           (void)guard;
                           non_void_result::run(
                               ret, std::forward<Fn>(fn), std::forward<Args>(args)...);
                       });
        sched.join();
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }
    // No-op if `result_type` is `void`
    return result_type(ret);
}

/**
 * Start the default scheduler and create the first fiber in it
 *
 * @param fn the entry point of the fiber
 * @param args the arguments for the fiber
 */
template <typename Fn, typename... Args>
auto fiberize(Fn&& fn, Args&&... args) -> typename std::result_of<Fn(Args...)>::type
{
    return fiberize_with_sched(
        fibio::scheduler::get_instance(), std::forward<Fn>(fn), std::forward<Args>(args)...);
}

} // End of namespace fibers

using fibers::fiberize_with_sched;
using fibers::fiberize;

} // End of namespace fibio

#if !defined(FIBIO_DONT_USE_DEFAULT_MAIN)
namespace fibio {
// Forward declaration of real entry point
int main(int argc, char* argv[]);
} // End of namespace fibio

int main(int argc, char* argv[])
{
    return fibio::fiberize(fibio::main, argc, argv);
}

#endif // !defined(FIBIO_DONT_USE_DEFAULT_MAIN)

#endif

max_stars_repo_name: mind-owner/fibio

max_issues_repo_name: learnerzhang/fibio

max_forks_repo_name: learnerzhang/fibio


text:
#include "source.hh"
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <iostream>
#include <ostream>
#include <string>

using namespace llang;
class NullBuffer : public std::streambuf {
public:
  int overflow(int c) { return c; }
};

enum Color {
  RED = 31,
  BLUE = 34,
  YELLOW = 33,
  GREEN = 32,
};

std::string c(const std::string& str, Color c, bool bold = true) {
  return (bold ? "\033[1;" : "\033[0;") + std::to_string(c) + "m" + str + "\033[0m";
}

// cant be const unfortunately
static auto dummy_buffer = NullBuffer();
static auto dummy_stream = std::ostream(&dummy_buffer);

bool Source::debugPrintMessages() const {
  if (messages.empty())
    return false;
  for (auto message : messages) {
    auto location = getLocation(message->span.start);
    auto line = getLine(location.first);
    auto trimmed = boost::trim_left_copy(line);
    switch (message->type) {
    case ERROR:
      std::cout << c("error: ", RED);
      break;
    case NOTE:
      std::cout << c("note: ", BLUE);
      break;
    case WARNING:
      std::cout << c("warning: ", YELLOW);
      break;
    }
    std::cout << (path.empty() ? "dummy/path/to/file.ext" : path) << ":" << location.first << ":"
              << location.second << "\n";
    std::cout << trimmed << "\n";
    std::cout << std::string(location.second - 1 - (line.size() - trimmed.size()), ' ');
    std::cout << c(std::string(message->span.length, '^'), GREEN);
    std::cout << "  " << message->message.str() << "\n";
  }
  return true;
}

std::size_t Source::lineCount() const {
  std::size_t count = 1;
  for (auto c : value) {
    if (c == '\n')
      count++;
  }
  return count;
}

std::string Source::getLine(std::size_t index) const {
  std::size_t count = 1;
  std::string buffer;
  for (auto c : value) {
    if (c == '\n') {
      if (count == index)
        return buffer;
      buffer.clear();
      count++;
    } else {
      buffer += c;
    }
  }
  return buffer;
}

std::pair<std::size_t, std::size_t> Source::getLocation(std::size_t index) const {
  std::size_t line_number = 1;
  std::size_t char_number = 1;
  for (const auto& c : value | boost::adaptors::indexed()) {
    if (c.index() == index) {
      return std::pair(line_number, char_number);
    }
    char_number++;
    if (c.value() == '\n') {
      line_number++;
      char_number = 1;
    }
  }
  throw std::runtime_error("Unexpected end of file");
}

std::string Span::getValue() const { return source->value.substr(start, length); }

Span Span::operator+(const Span& other) const {
  if (this->source != other.source) {
    throw std::runtime_error("Spans must be from the same source to join");
  }

  const Span& first = other.start < this->start ? other : *this;
  const Span& second = other.start < this->start ? *this : other;

  return Span(source, first.start, first.length + second.length);
}

Span Span::subspan(int sub_start, int end) const {
  if (end < 0) {
    return subspan(sub_start, length + end);
  }
  return Span(source, start + sub_start, end - sub_start);
}

std::ostream& Span::expect(bool assertion, MessageType type) {
  if (!assertion) {
    return fail(type);
  }
  return dummy_stream;
}

std::ostream& Span::fail(MessageType type) {
  auto message = std::make_shared<Message>(*this, type);
  source->messages.push_back(message);
  return message->message;
}

std::size_t Span::end() const { return start + length == 0 ? 0 : (length - 1); }

ext: cc

max_stars_repo_name: zacklukem/llang

max_issues_repo_name: zacklukem/llang

max_forks_repo_name: zacklukem/llang


text:
#include <boost/test/unit_test.hpp>
#include "Utils.h"
#include "Mocks.h"
#include "L4/HashTable/Config.h"
#include "L4/HashTable/IHashTable.h"
#include "L4/LocalMemory/HashTableManager.h"

namespace L4
{
namespace UnitTests
{

class HashTableManagerTestsFixture
{
protected:
    template <typename Store>
    void ValidateRecord(
        const Store& store,
        const char* expectedKeyStr,
        const char* expectedValueStr)
    {
        IReadOnlyHashTable::Value actualValue;
        auto expectedValue = Utils::ConvertFromString<IReadOnlyHashTable::Value>(expectedValueStr);
        BOOST_CHECK(store.Get(Utils::ConvertFromString<IReadOnlyHashTable::Key>(expectedKeyStr), actualValue));
        BOOST_CHECK(actualValue.m_size == expectedValue.m_size);
        BOOST_CHECK(!memcmp(actualValue.m_data, expectedValue.m_data, expectedValue.m_size));
    }

    MockEpochManager m_epochManager;
    std::allocator<void> m_allocator;
};

BOOST_FIXTURE_TEST_SUITE(HashTableManagerTests, HashTableManagerTestsFixture)

BOOST_AUTO_TEST_CASE(HashTableManagerTest)
{
    LocalMemory::HashTableManager htManager;
    const auto ht1Index = htManager.Add(
        HashTableConfig("HashTable1", HashTableConfig::Setting(100U)),
        m_epochManager,
        m_allocator);
    const auto ht2Index = htManager.Add(
        HashTableConfig("HashTable2", HashTableConfig::Setting(200U)),
        m_epochManager,
        m_allocator);

    {
        auto& hashTable1 = htManager.GetHashTable("HashTable1");
        hashTable1.Add(
            Utils::ConvertFromString<IReadOnlyHashTable::Key>("HashTable1Key"),
            Utils::ConvertFromString<IReadOnlyHashTable::Value>("HashTable1Value"));

        auto& hashTable2 = htManager.GetHashTable("HashTable2");
        hashTable2.Add(
            Utils::ConvertFromString<IReadOnlyHashTable::Key>("HashTable2Key"),
            Utils::ConvertFromString<IReadOnlyHashTable::Value>("HashTable2Value"));
    }

    ValidateRecord(
        htManager.GetHashTable(ht1Index),
        "HashTable1Key",
        "HashTable1Value");

    ValidateRecord(
        htManager.GetHashTable(ht2Index),
        "HashTable2Key",
        "HashTable2Value");
}

BOOST_AUTO_TEST_CASE(HashTableManagerTestForSerialzation)
{
    HashTableConfig htConfig{ "HashTable1", HashTableConfig::Setting(100U) };
    std::ostringstream outStream;

    std::vector<std::pair<std::string, std::string>> testData;
    for (std::int32_t i = 0; i < 10; ++i)
    {
        testData.emplace_back(
            "key" + std::to_string(i),
            "val" + std::to_string(i));
    }

    // Serialize a hash table.
    {
        LocalMemory::HashTableManager htManager;
        const auto ht1Index = htManager.Add(htConfig, m_epochManager, m_allocator);

        auto& hashTable1 = htManager.GetHashTable("HashTable1");

        for (const auto& kvPair : testData)
        {
            hashTable1.Add(
                Utils::ConvertFromString<IReadOnlyHashTable::Key>(kvPair.first.c_str()),
                Utils::ConvertFromString<IReadOnlyHashTable::Value>(kvPair.second.c_str()));
        }

        auto serializer = hashTable1.GetSerializer();
        serializer->Serialize(outStream, {});
    }

    // Deserialize the hash table.
    {
        htConfig.m_serializer.emplace(
            std::make_shared<std::istringstream>(outStream.str()));

        LocalMemory::HashTableManager htManager;
        const auto ht1Index = htManager.Add(htConfig, m_epochManager, m_allocator);

        auto& hashTable1 = htManager.GetHashTable("HashTable1");
        BOOST_CHECK_EQUAL(
            hashTable1.GetPerfData().Get(HashTablePerfCounter::RecordsCount),
            testData.size());

        for (const auto& kvPair : testData)
        {
            ValidateRecord(
                hashTable1,
                kvPair.first.c_str(),
                kvPair.second.c_str());
        }
    }
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace UnitTests
} // namespace L4


text:
// Copyright (c) 2017-2019 The Raven Core developers
// Copyright (c) 2020-2021 The Hive Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <util.h>
#include <consensus/params.h>
#include <script/ismine.h>
#include <tinyformat.h>
#include "masternodedb.h"
#include "masternodes.h"
#include "validation.h"

#include <boost/thread.hpp>

static const char MASTERNODE_FLAG = 'A';
static const char MASTERNODE_ADDRESS_QUANTITY_FLAG = 'B';
static const char ADDRESS_MASTERNODE_QUANTITY_FLAG = 'C';
static const char MY_MASTERNODE_FLAG = 'M';
static const char BLOCK_MASTERNODE_UNDO_DATA = 'U';
static const char MEMPOOL_UPDATED_TX = 'Z';

static size_t MAX_DATABASE_RESULTS = 50000;

CMasterNodesDB::CMasterNodesDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "masternodes", nCacheSize, fMemory, fWipe) {
}

bool CMasterNodesDB::WriteMasterNodeData(const CNewMasterNode &masternode, const int nHeight, const uint256& blockHash)
{
    CDatabasedMasterNodeData data(masternode, nHeight, blockHash);
    return Write(std::make_pair(MASTERNODE_FLAG, masternode.strName), data);
}

bool CMasterNodesDB::WriteMasterNodeAddressQuantity(const std::string &masternodeName, const std::string &address, const CAmount &quantity)
{
    return Write(std::make_pair(MASTERNODE_ADDRESS_QUANTITY_FLAG, std::make_pair(masternodeName, address)), quantity);
}

bool CMasterNodesDB::WriteAddressMasterNodeQuantity(const std::string &address, const std::string &masternodeName, const CAmount& quantity) {
    return Write(std::make_pair(ADDRESS_MASTERNODE_QUANTITY_FLAG, std::make_pair(address, masternodeName)), quantity);
}

bool CMasterNodesDB::ReadMasterNodeData(const std::string& strName, CNewMasterNode& masternode, int& nHeight, uint256& blockHash)
{

    CDatabasedMasterNodeData data;
    bool ret =  Read(std::make_pair(MASTERNODE_FLAG, strName), data);

    if (ret) {
        masternode = data.masternode;
        nHeight = data.nHeight;
        blockHash = data.blockHash;
    }

    return ret;
}

bool CMasterNodesDB::ReadMasterNodeAddressQuantity(const std::string& masternodeName, const std::string& address, CAmount& quantity)
{
    return Read(std::make_pair(MASTERNODE_ADDRESS_QUANTITY_FLAG, std::make_pair(masternodeName, address)), quantity);
}

bool CMasterNodesDB::ReadAddressMasterNodeQuantity(const std::string &address, const std::string &masternodeName, CAmount& quantity) {
    return Read(std::make_pair(ADDRESS_MASTERNODE_QUANTITY_FLAG, std::make_pair(address, masternodeName)), quantity);
}

bool CMasterNodesDB::EraseMasterNodeData(const std::string& masternodeName)
{
    return Erase(std::make_pair(MASTERNODE_FLAG, masternodeName));
}

bool CMasterNodesDB::EraseMyMasterNodeData(const std::string& masternodeName)
{
    return Erase(std::make_pair(MY_MASTERNODE_FLAG, masternodeName));
}

bool CMasterNodesDB::EraseMasterNodeAddressQuantity(const std::string &masternodeName, const std::string &address) {
    return Erase(std::make_pair(MASTERNODE_ADDRESS_QUANTITY_FLAG, std::make_pair(masternodeName, address)));
}

bool CMasterNodesDB::EraseAddressMasterNodeQuantity(const std::string &address, const std::string &masternodeName) {
    return Erase(std::make_pair(ADDRESS_MASTERNODE_QUANTITY_FLAG, std::make_pair(address, masternodeName)));
}

bool EraseAddressMasterNodeQuantity(const std::string &address, const std::string &masternodeName);

bool CMasterNodesDB::WriteBlockUndoMasterNodeData(const uint256& blockhash, const std::vector<std::pair<std::string, CBlockMasterNodeUndo> >& masternodeUndoData)
{
    return Write(std::make_pair(BLOCK_MASTERNODE_UNDO_DATA, blockhash), masternodeUndoData);
}

bool CMasterNodesDB::ReadBlockUndoMasterNodeData(const uint256 &blockhash, std::vector<std::pair<std::string, CBlockMasterNodeUndo> > &masternodeUndoData)
{
    // If it exists, return the read value.
    if (Exists(std::make_pair(BLOCK_MASTERNODE_UNDO_DATA, blockhash)))
           return Read(std::make_pair(BLOCK_MASTERNODE_UNDO_DATA, blockhash), masternodeUndoData);

    // If it doesn't exist, we just return true because we don't want to fail just because it didn't exist in the db
    return true;
}

bool CMasterNodesDB::WriteUpdatedMempoolState()
{
    return Write(MEMPOOL_UPDATED_TX, mapUpdatedMasterNodes);
}

bool CMasterNodesDB::ReadUpdatedMempoolState()
{
    mapUpdatedMasterNodes.clear();
    mapUpdatedTx.clear();
    // If it exists, return the read value.
    bool rv = Read(MEMPOOL_UPDATED_TX, mapUpdatedMasterNodes);
    if (rv) {
        for (auto pair : mapUpdatedMasterNodes)
            mapUpdatedTx.insert(std::make_pair(pair.second, pair.first));
    }
    return rv;
}

bool CMasterNodesDB::LoadMasterNodes()
{
    std::unique_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(std::make_pair(MASTERNODE_FLAG, std::string()));

    // Load masternodes
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, std::string> key;
        if (pcursor->GetKey(key) && key.first == MASTERNODE_FLAG) {
            CDatabasedMasterNodeData data;
            if (pcursor->GetValue(data)) {
                pmasternodesCache->Put(data.masternode.strName, data);
                pcursor->Next();

                // Loaded enough from database to have in memory.
                // No need to load everything if it is just going to be removed from the cache
                if (pmasternodesCache->Size() == (pmasternodesCache->MaxSize() / 2))
                    break;
            } else {
                return error("%s: failed to read masternode", __func__);
            }
        } else {
            break;
        }
    }

    if (fMasterNodeIndex) {
        std::unique_ptr<CDBIterator> pcursor3(NewIterator());
        pcursor3->Seek(std::make_pair(MASTERNODE_ADDRESS_QUANTITY_FLAG, std::make_pair(std::string(), std::string())));

        // Load mapMasterNodeAddressAmount
        while (pcursor3->Valid()) {
            boost::this_thread::interruption_point();
            std::pair<char, std::pair<std::string, std::string> > key; // <MasterNode Name, Address> -> Quantity
            if (pcursor3->GetKey(key) && key.first == MASTERNODE_ADDRESS_QUANTITY_FLAG) {
                CAmount value;
                if (pcursor3->GetValue(value)) {
                    pmasternodes->mapMasterNodesAddressAmount.insert(
                            std::make_pair(std::make_pair(key.second.first, key.second.second), value));
                    if (pmasternodes->mapMasterNodesAddressAmount.size() > MAX_CACHE_MASTERNODES_SIZE)
                        break;
                    pcursor3->Next();
                } else {
                    return error("%s: failed to read my address quantity from database", __func__);
                }
            } else {
                break;
            }
        }
    }

    return true;
}

bool CMasterNodesDB::MasterNodeDir(std::vector<CDatabasedMasterNodeData>& masternodes, const std::string filter, const size_t count, const long start)
{
    FlushStateToDisk();

    std::unique_ptr<CDBIterator> pcursor(NewIterator());
    pcursor->Seek(std::make_pair(MASTERNODE_FLAG, std::string()));

    auto prefix = filter;
    bool wildcard = prefix.back() == '*';
    if (wildcard)
        prefix.pop_back();

    size_t skip = 0;
    if (start >= 0) {
        skip = start;
    }
    else {
        // compute table size for backwards offset
        long table_size = 0;
        while (pcursor->Valid()) {
            boost::this_thread::interruption_point();

            std::pair<char, std::string> key;
            if (pcursor->GetKey(key) && key.first == MASTERNODE_FLAG) {
                if (prefix == "" ||
                    (wildcard && key.second.find(prefix) == 0) ||
                    (!wildcard && key.second == prefix)) {
                    table_size += 1;
                }
            }
            pcursor->Next();
        }
        skip = table_size + start;
        pcursor->SeekToFirst();
    }

    size_t loaded = 0;
    size_t offset = 0;

    // Load masternodes
    while (pcursor->Valid() && loaded < count) {
        boost::this_thread::interruption_point();

        std::pair<char, std::string> key;
        if (pcursor->GetKey(key) && key.first == MASTERNODE_FLAG) {
            if (prefix == "" ||
                    (wildcard && key.second.find(prefix) == 0) ||
                    (!wildcard && key.second == prefix)) {
                if (offset < skip) {
                    offset += 1;
                }
                else {
                    CDatabasedMasterNodeData data;
                    if (pcursor->GetValue(data)) {
                        masternodes.push_back(data);
                        loaded += 1;
                    } else {
                        return error("%s: failed to read masternode", __func__);
                    }
                }
            }
            pcursor->Next();
        } else {
            break;
        }
    }

    return true;
}

bool CMasterNodesDB::AddressDir(std::vector<std::pair<std::string, CAmount> >& vecMasterNodeAmount, int& totalEntries, const bool& fGetTotal, const std::string& address, const size_t count, const long start)
{
    FlushStateToDisk();

    std::unique_ptr<CDBIterator> pcursor(NewIterator());
    pcursor->Seek(std::make_pair(ADDRESS_MASTERNODE_QUANTITY_FLAG, std::make_pair(address, std::string())));

    if (fGetTotal) {
        totalEntries = 0;
        while (pcursor->Valid()) {
            boost::this_thread::interruption_point();

            std::pair<char, std::pair<std::string, std::string> > key;
            if (pcursor->GetKey(key) && key.first == ADDRESS_MASTERNODE_QUANTITY_FLAG && key.second.first == address) {
                totalEntries++;
            }
            pcursor->Next();
        }
        return true;
    }

    size_t skip = 0;
    if (start >= 0) {
        skip = start;
    }
    else {
        // compute table size for backwards offset
        long table_size = 0;
        while (pcursor->Valid()) {
            boost::this_thread::interruption_point();

            std::pair<char, std::pair<std::string, std::string> > key;
            if (pcursor->GetKey(key) && key.first == ADDRESS_MASTERNODE_QUANTITY_FLAG && key.second.first == address) {
                table_size += 1;
            }
            pcursor->Next();
        }
        skip = table_size + start;
        pcursor->SeekToFirst();
    }

    size_t loaded = 0;
    size_t offset = 0;

    // Load masternodes
    while (pcursor->Valid() && loaded < count && loaded < MAX_DATABASE_RESULTS) {
        boost::this_thread::interruption_point();

        std::pair<char, std::pair<std::string, std::string> > key;
        if (pcursor->GetKey(key) && key.first == ADDRESS_MASTERNODE_QUANTITY_FLAG && key.second.first == address) {
                if (offset < skip) {
                    offset += 1;
                }
                else {
                    CAmount amount;
                    if (pcursor->GetValue(amount)) {
                        vecMasterNodeAmount.emplace_back(std::make_pair(key.second.second, amount));
                        loaded += 1;
                    } else {
                        return error("%s: failed to Address MasterNode Quanity", __func__);
                    }
                }
            pcursor->Next();
        } else {
            break;
        }
    }

    return true;
}

// Can get to total count of addresses that belong to a certain masternode_name, or get you the list of all address that belong to a certain masternode_name
bool CMasterNodesDB::MasterNodeAddressDir(std::vector<std::pair<std::string, CAmount> >& vecAddressAmount, int& totalEntries, const bool& fGetTotal, const std::string& masternodeName, const size_t count, const long start)
{
    FlushStateToDisk();

    std::unique_ptr<CDBIterator> pcursor(NewIterator());
    pcursor->Seek(std::make_pair(MASTERNODE_ADDRESS_QUANTITY_FLAG, std::make_pair(masternodeName, std::string())));

    if (fGetTotal) {
        totalEntries = 0;
        while (pcursor->Valid()) {
            boost::this_thread::interruption_point();

            std::pair<char, std::pair<std::string, std::string> > key;
            if (pcursor->GetKey(key) && key.first == MASTERNODE_ADDRESS_QUANTITY_FLAG && key.second.first == masternodeName) {
                totalEntries += 1;
            }
            pcursor->Next();
        }
        return true;
    }

    size_t skip = 0;
    if (start >= 0) {
        skip = start;
    }
    else {
        // compute table size for backwards offset
        long table_size = 0;
        while (pcursor->Valid()) {
            boost::this_thread::interruption_point();

            std::pair<char, std::pair<std::string, std::string> > key;
            if (pcursor->GetKey(key) && key.first == MASTERNODE_ADDRESS_QUANTITY_FLAG && key.second.first == masternodeName) {
                table_size += 1;
            }
            pcursor->Next();
        }
        skip = table_size + start;
        pcursor->SeekToFirst();
    }

    size_t loaded = 0;
    size_t offset = 0;

    // Load masternodes
    while (pcursor->Valid() && loaded < count && loaded < MAX_DATABASE_RESULTS) {
        boost::this_thread::interruption_point();

        std::pair<char, std::pair<std::string, std::string> > key;
        if (pcursor->GetKey(key) && key.first == MASTERNODE_ADDRESS_QUANTITY_FLAG && key.second.first == masternodeName) {
            if (offset < skip) {
                offset += 1;
            }
            else {
                CAmount amount;
                if (pcursor->GetValue(amount)) {
                    vecAddressAmount.emplace_back(std::make_pair(key.second.second, amount));
                    loaded += 1;
                } else {
                    return error("%s: failed to MasterNode Address Quanity", __func__);
                }
            }
            pcursor->Next();
        } else {
            break;
        }
    }

    return true;
}

bool CMasterNodesDB::MasterNodeDir(std::vector<CDatabasedMasterNodeData>& masternodes)
{
    return CMasterNodesDB::MasterNodeDir(masternodes, "*", MAX_SIZE, 0);
}


text:
// Copyright 2020 Dow, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "LogFilterProxyModel.h"

#include <QModelIndex>

#include <boost/log/trivial.hpp>

LogFilterProxyModel::LogFilterProxyModel(QObject *parent)
    : QSortFilterProxyModel(parent)
{
}

void LogFilterProxyModel::setTagVisible(const QString& tag, bool visible)
{
    tagVisibility[tag] = visible;
    invalidateFilter();
}

void LogFilterProxyModel::setErrorsVisible(bool visible)
{
    errorsVisible = visible;
    invalidateFilter();
}

void LogFilterProxyModel::setMessagesVisible(bool visible)
{
    messagesVisible = visible;
    invalidateFilter();
}

void LogFilterProxyModel::setWarningsVisible(bool visible)
{
    warningsVisible = visible;
    invalidateFilter();
}

bool LogFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
{
    // Severity is the UserRole associated with column 0.
    QModelIndex severityIndex = sourceModel()->index(row, 0, parent);
    int severity = sourceModel()->data(severityIndex, Qt::UserRole).toInt();

    QModelIndex tagIndex = sourceModel()->index(row, filterKeyColumn(), parent);
    QString tag = sourceModel()->data(tagIndex, Qt::DisplayRole).toString();

    bool accept = true;
    switch (severity) {
    case boost::log::trivial::trace:
    case boost::log::trivial::debug:
    case boost::log::trivial::info:
        accept = messagesVisible;
        break;
    case boost::log::trivial::warning:
        accept = warningsVisible;
        break;
    case boost::log::trivial::error:
    case boost::log::trivial::fatal:
        accept = errorsVisible;
        break;
    default:
        break;
    }

    // Exclude any tags where visibility is explicitly set to false.
    accept &= tagVisibility.value(tag, true);

    return accept;
}

max_stars_repo_name: sofea-model/sofea

max_issues_repo_name: sofea-model/sofea

max_forks_repo_name: sofea-model/sofea