CUDB Dynamic Library for Distribution

Contents

1Introduction
1.1Scope
1.2Revision Information
1.3Target Groups
1.4Prerequisites
1.5Typographic Conventions

2

Overview
2.1Description
2.1.1Configuring the Dynamic Library
2.1.2Compiling the Dynamic Library
2.1.3Installing the Dynamic Library

3

Examples
3.1Basic Example Library
3.2Testing the Dynamic Library
3.3Header File Template

Glossary

Reference List

1   Introduction

This document describes how to develop customized subscriber data distribution policies in the Ericsson Centralized User Database (CUDB) by an external library.

1.1   Scope

During provisioning time, CUDB is using a default policy to determine the Data Store Unit Group (DSG) for each Distribution Entry (DE) provisioned by the system. The goal of this procedure is to keep a balanced memory occupation level in all the DSGs of the system.

However, to suit specific customer needs, CUDB supports the configuration and execution of custom data distribution policies that override the default policy. This document describes how to configure a custom data distribution policy. Refer to CUDB LDAP Data Access, Reference [1] for more information on data distribution.

1.2   Revision Information

Rev. A This document is based on 4/19817-HDA 104 03/9, and contains editorial changes only.

1.3   Target Groups

This document is intended for developers who implement custom distribution algorithms for provisioning users in accordance with customer requests.

1.4   Prerequisites

Users of this document must have knowledge and experience in C++ programming.

1.5   Typographic Conventions

Typographic conventions can be found in the following document:

2   Overview

The default CUDB subscriber data distribution policy is based on detecting the memory occupation of the DSGs: the system aims to select DSGs with lower memory occupation levels to use as storage when distributing data. Optionally, the multiple geographical areas feature can also be used to configure data distribution: refer to CUDB Multiple Geographical Areas, Reference [2] for more information.

Custom data distribution policies can be configured by using Dynamically Loaded (DL) Linux libraries, implemented with C++ and compiled for 64-bit systems by using a generic Linux C++ compiler, such as gcc. The procedure is described in the next sections in more detail.

2.1   Description

This section provides detailed description for the CUDB Dynamic Library feature, and provides examples for the compilation process and library installation.

A CUDB dynamic library consists of a header file defining the types of the distribution functions running in the system, along with the implementation of the functions.

2.1.1   Configuring the Dynamic Library

The parameters of the external library are provided by using generic structures. The structures are defined in the cudb_dist_ext_func.h header file which can be included in the library compilation.

The header file contains two important pieces of information:

Both of these must be copied from the header file, as the file is not distributed. The structures and functions are described below in more detail.

2.1.1.1   Configuring Structure Definitions

Example 1 provides an example of the structure definitions declared in cudb_dist_ext_func.h. See Section 2.1.1.2 for an explanation of the functions included in this example.

Example 1   Structure Definitions

#include <vector>

typedef struct
{
  long	cv_len;
  char	*cv_val;
} charVal;

typedef struct
{
  charVal cName;
  vector<charVal> cValue;
} argStruct;

typedef vector<argStruct*>	arg_attribs;
 // e.g. {"mscId", "1234"} , {"ZoneId", "1"} , ...
typedef vector<argStruct*>	arg_dyndata;
 // e.g. {"usage", "1 50"}
typedef vector<argStruct*>	arg_confdata;
 // e.g. {"zone", "1 1 2"} , {"default_zone", "1"} ,
      // {"limit", "99"} , ...

2.1.1.2   Declaring External Functions

Example 2 provides an example of the external functions that can be declared in the header file:

Example 2   Declaration of External Functions

extern “C”{
    int external_distalloc
    (arg_attribs arg1,
    arg_dyndata arg2,
    arg_confdata arg3,
    char* errorMsg);
}

#define EXTFUNC_NAME "external_distalloc"
#define ERROR_NO_DSG_DEFAULT_DISTRIBUTION -1
#define ERROR_NO_DSG_NO_DISTRIBUTION -9

The functions used in Example 2 are as follows:

In case of errors, the relevant events are logged according to CUDB Node Logging Events, Reference [3].

The external functions can receive the following fixed keywords with their parameters:

Example 3   Implementing arg1 containing ZoneId 1

// param 1 : dn attributes
arg_attribs arg1;

argStruct* a1 = new argStruct();
charVal cvname;
cvname.cv_len = 6;
cvname.cv_val = new char[7];
strcpy(cvname.cv_val,"ZoneId\0");
a1->cName = cvname;

charVal cvvalue;
cvvalue.cv_len = 1;
cvvalue.cv_val = new char[2];
strcpy(cvvalue.cv_val,"1\0");
(a1->cValue).push_back(cvvalue);

arg1.push_back(a1);

Example 4   Implementing Non-Provisioning List

// param 2 : dsgs list
arg_dyndata arg2;

argStruct* a2 = new argStruct();

charVal cvname2;
cvname2.cv_len = 5;
cvname2.cv_val = new char[6];
strcpy(cvname2.cv_val,"usage\0");
a2->cName = cvname2;

charVal cvDsgId;
cvDsgId.cv_len = 1;
cvDsgId.cv_val = new char[2];
strcpy(cvDsgId.cv_val,"1\0");
(a2->cValue).push_back(cvDsgId);
            	
charVal cvDsgUs;
cvDsgUs.cv_len = 2;
cvDsgUs.cv_val = new char[4];
strcpy(cvDsgUs.cv_val,"50\0");
(a2->cValue).push_back(cvDsgUs);
            	
arg2.push_back(a2);

a2 = new argStruct();

charVal cvname2Prov;
cvname2Prov.cv_len = 13; 
cvname2Prov.cv_val = new char[14]; 
strcpy(cvname2Prov.cv_val,"non_prov_list\0");
a2->cName = cvname2Prov; 
charVal cvDsgIdProv; 
cvDsgIdProv.cv_len = 1; 
cvDsgIdProv.cv_val = new char[2]; 
strcpy(cvDsgIdProv.cv_val,"1\0"); 
(a2->cValue).push_back(cvDsgIdProv)

arg2.push_back(a2);

Example 5   Implementing arg3 Vector for zone

// param 3 : config data
arg_confdata arg3;

argStruct* a3 = new argStruct();
charVal cvname3;
cvname3.cv_len = 4;
cvname3.cv_val = new char[5];
strcpy(cvname3.cv_val,"zone\0");
a3->cName = cvname3;

charVal cvZone;
cvZone.cv_len = 1;
cvZone.cv_val = new char[2];
strcpy(cvZone.cv_val,"1\0");
(a3->cValue).push_back(cvZone);
            
charVal cvDsg1;
cvDsg1.cv_len = 1;
cvDsg1.cv_val = new char[2];
strcpy(cvDsg1.cv_val,"1\0");
(a3->cValue).push_back(cvDsg1);

charVal cvDsg2;
cvDsg2.cv_len = 1;
cvDsg2.cv_val = new char[2];
strcpy(cvDsg2.cv_val,"2\0");
(a3->cValue).push_back(cvDsg2);

arg3.push_back(a3);

2.1.2   Compiling the Dynamic Library

The DL must be compiled in 64 bits using a standard C++ compiler, such as Linux gcc.

Example 6 provides generic compiler and linker commands for a DL called testDL.

Example 6   Compiler and Linker Commands

Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP
    -MF"testDL.d" -MT"testDL.d" -o"testDL.o"
    "./testDL.cpp"
Invoking: GCC C++ Linker
g++ -shared -o"libcudbDistrDL.so"  ./testDL.o

2.1.3   Installing the Dynamic Library

For the detailed steps of installing or uninstalling a DL, refer to CUDB System Administrator Guide, Reference [5].

Note:  
After installing the DL, the new distribution policy is applied. Uninstall the custom DL to revert to the default distribution policy.

3   Examples

This section contains additional examples to get a better understanding on how dynamic libraries are created, compiled and deployed. The section contains the following examples:

3.1   Basic Example Library

The new shared library must be coded using C++. Once implemented, the DL must be installed as described in Section 2.1.3.

Example 7 shows a new algorithm that returns the DSG with the lowest occupancy, excluding DSG number 0. The basic CPP file looks as follows:

Example 7   New Algorithm Returning DSG with Lowest Occupancy

#include "cudb_dist_ext_func.h"
 
#include <vector>
#include <string.h>
#include <stdlib.h>
extern "C" {

int external_distalloc(arg_attribs entryAttrs,
                       arg_dyndata dynamicData,
                       arg_confdata configData,
                       char* retErrorCode){
   int usage_ret = 0;
   int i_ret = -1;
   vector <argStruct*>::iterator dynamicData_it;

   for (dynamicData_it = dynamicData.begin(); dynamicData_it != dynamicData.end(); dynamicData_it++){
      argStruct * dynData_Ptr;
      dynData_Ptr = *dynamicData_it;
      vector<charVal>::iterator dynData_cValue_it = (dynData_Ptr->cValue).begin();

      if ( strcmp(dynData_Ptr->cName.cv_val, "usage")==0 ){
         int idDSG = atoi((*dynData_cValue_it).cv_val);
         dynData_cValue_it++;
         if(idDSG!=0){
            if(i_ret == -1){
               i_ret = idDSG;
               usage_ret = atoi((*dynData_cValue_it).cv_val);
            }else if(atoi((*dynData_cValue_it).cv_val) < usage_ret){
               i_ret = idDSG;
            }
         } //idDSG!=0
      }
   } //for
   return (i_ret);
}

} // extern "C"

The above code can be compiled with the following commands:

3.2   Testing the Dynamic Library

Example 8 provides a program that can be used to test external libraries:

Example 8   Program Using External Library

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>

#include "cudb_dist_ext_func.h"

int extFunction(char*);


int main()
{
  char retErrorCode[255];
  memset((char*)retErrorCode, '\0', 255);
  int ret = extFunction(retErrorCode);

   printf("\n Ret Value = %d\n",ret);
	  printf(" Ret Error Msg = %s\n\n", retErrorCode);

	  return 0;
}


  int extFunction(char* retErrorCode)
{
  // handling DL
  void *handle;
  char *dl_error;
  int retValue = -1;
 
  handle = dlopen("./libcudbDistr.so", RTLD_LAZY);
  if (handle)
  {
   // External funct exists. Trying to apply ext algorithm
   int (*external_distalloc)(arg_attribs,
                             arg_dyndata,
                             arg_confdata,
                             char*);  	
   *(void**) (& external_distalloc) =
                    dlsym(handle, "external_distalloc");
   if ((dl_error = dlerror()) != NULL) {
      // Error when accessing distribution external library
      retValue = -2;
   }else{
     // Prepare params to external function
 
     // Param 1 : dn attributes
     arg_attribs entryAttrs;

     argStruct* zoneIdAttr = new argStruct();
     charVal cvname;
     cvname.cv_len = 6;
     cvname.cv_val = new char[7];
     strcpy(cvname.cv_val,"ZoneId\0");
     zoneIdAttr->cName = cvname;

     charVal cvvalue;
     cvvalue.cv_len = 1;
     cvvalue.cv_val = new char[2];
     strcpy(cvvalue.cv_val,"1\0");
     (zoneIdAttr->cValue).push_back(cvvalue);

     entryAttrs.push_back(zoneIdAttr);



     // Param 2 : DSG memory occupation
     arg_dyndata dynamicData;

     //DSG 1 usage : {"usage",{"1","50"}} 
     argStruct* dsg1Usage = new argStruct();

     charVal dsg1Usage_cvname;
     dsg1Usage_cvname.cv_len = 5;
     dsg1Usage_cvname.cv_val = new char[6];
     strcpy(dsg1Usage_cvname.cv_val,"usage\0");
     dsg1Usage->cName = dsg1Usage_cvname;

     charVal cvDsg1Id;
     cvDsg1Id.cv_len = 1;
     cvDsg1Id.cv_val = new char[2];
     strcpy(cvDsg1Id.cv_val,"1\0");
     (dsg1Usage->cValue).push_back(cvDsg1Id);

     charVal cvDsg1Usage;
     cvDsg1Usage.cv_len = 2;
     cvDsg1Usage.cv_val = new char[3];
     strcpy(cvDsg1Usage.cv_val,"50\0");
     (dsg1Usage->cValue).push_back(cvDsg1Usage);

     dynamicData.push_back(dsg1Usage);

     //DSG 2 usage {"usage",{"2","40"}}
     argStruct* dsg2Usage = new argStruct();

     charVal dsg2Usage_cvname;
     dsg2Usage_cvname.cv_len=5;
     dsg2Usage_cvname.cv_val=new char[6];
     strcpy(dsg2Usage_cvname.cv_val,"usage\0");
     dsg2Usage->cName = dsg2Usage_cvname;

     charVal cvDsg2Id;
     cvDsg2Id.cv_len = 1;
     cvDsg2Id.cv_val = new char[2];
     strcpy(cvDsg2Id.cv_val,"2\0");
     (dsg2Usage->cValue).push_back(cvDsg2Id);

     charVal cvDsg2Us;
     cvDsg2Us.cv_len = 2;
     cvDsg2Us.cv_val = new char[3];
     strcpy(cvDsg2Us.cv_val,"40\0");
     (dsg2Usage->cValue).push_back(cvDsg2Us);

     dynamicData.push_back(dsg2Usage);



     // Param 3 : config data
     arg_confdata configData;
     // Zone configuration : { "zone", {"1","1","2"} }
     argStruct* zoneConfig = new argStruct();
     charVal cvname3;
     cvname3.cv_len = 4;
     cvname3.cv_val = new char[5];
     strcpy(cvname3.cv_val,"zone\0");
     zoneConfig->cName = cvname3;

     charVal cvZone;
     cvZone.cv_len = 1;
     cvZone.cv_val = new char[2];
     strcpy(cvZone.cv_val,"1\0");
     (zoneConfig->cValue).push_back(cvZone);

     charVal cvDsg1;
     cvDsg1.cv_len = 1;
     cvDsg1.cv_val = new char[2];
     strcpy(cvDsg1.cv_val,"1\0");
     (zoneConfig->cValue).push_back(cvDsg1);

     charVal cvDsg2;
     cvDsg2.cv_len = 1;
     cvDsg2.cv_val = new char[2];
     strcpy(cvDsg2.cv_val,"2\0");
     (zoneConfig->cValue).push_back(cvDsg2);

     configData.push_back(zoneConfig);



     // external function
     retValue = (*external_distalloc)
                        (entryAttrs,
                         dynamicData,
                         configData,
                         retErrorCode);

     entryAttrs.clear();
     dynamicData.clear();
     configData.clear();

   }

   dlclose(handle);
 }

 return (retValue);

}

The above code can be compiled with the following commands:

3.3   Header File Template

Example 9 provides a template for the cudb_dist_ext_func.h header file.

Example 9   Header File Template

#ifndef CUDB_DIST_EXT_FUNC_H_
#define CUDB_DIST_EXT_FUNC_H_

#include <vector>

using namespace std;

// Structures used by external function
typedef struct
{
	long	cv_len;
	char	*cv_val;
} charVal;

typedef struct
{
	charVal cName;
	vector<charVal> cValue;
} argStruct;

typedef vector<argStruct*>	arg_attribs;	// e.g. {"mscId", 1, "1234"} , {"ZoneId", 1, "1"} , ...
typedef vector<argStruct*>	arg_dyndata;	// e.g. {"usage", 2, "1 50"} , ...
typedef vector<argStruct*>	arg_confdata;	// e.g. {"zone", 4, "1 1 2 3"} , {"default_zone", 1, "1"} , {"limit", 1, "80"} , ...


// Prototype of external function
//   Params:
//     arg_attribs  : attributes of the distributed entry to be provisioned
//     arg_dyndata  : dynamic data ( memory usage and list of dsg not available for provisioning)
//     arg_confdata : static configuration data ( zones, default zone and occupancy limit )
//     char* [out]  : returned error message
//   Return values:
//     -1  : external algorithm execution failed; default algorithm must be applied
//     -9  : no DSG must be selected, an error must be returned
//   otherwise, return selected DSG
int (*cudb_external_distalloc) (arg_attribs entryAttrs, arg_dyndata dynamicData, arg_confdata configData, char* errMsg);

#define EXTFUNC_NAME	"external_distalloc"
#define ERROR_NO_DSG_DEFAULT_DISTRIBUTION -1 
#define ERROR_NO_DSG_NO_DISTRIBUTION -9

#endif /*CUDB_DIST_EXT_FUNC_H_*/

Glossary

For the terms, definitions, acronyms and abbreviations used in this document, refer to CUDB Glossary of Terms and Acronyms, Reference [6].


Reference List

CUDB Documents
[1] CUDB LDAP Data Access.
[2] CUDB Multiple Geographical Areas.
[3] CUDB Node Logging Events.
[4] CUDB LDAP Interwork Description.
[5] CUDB System Administrator Guide.
[6] CUDB Glossary of Terms and Acronyms.