Open Ethernet Networking (OpEN) API Guide and Reference Manual  3.6.0.3
multi_threaded_app_example.c
/*********************************************************************
*
* Copyright 2016-2018 Broadcom.
*
* 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.
*
*************************************************************************
*
* @filename multi_threaded_app_example.c
*
* @purpose Multi-Threaded Application Example.
*
* @component OPEN
*
* @note
*
* @create 5/3/2016
*
* @end
*
***************************************************************************/
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include "rpcclt_openapi.h"
#include "proc_util.h"
#include "openapi_common.h"
#define MAX_THREADS 2
#define MAX_ITER 8
#define MAX_TRIES 1000
#define MIN_SLEEP 1
/* instance-specific thread info */
typedef struct
{
pthread_t thread_id; /* provided by pthread_create() */
int inst_num; /* instance number (1-based) */
int num_iter; /* number of test iterations to perform */
int sleep_time; /* delay interval between iterations */
} thread_info_t;
/***************************************************************/
static void * check_connect_task(void *arg)
{
openapiClientHandle_t clientHandle;
thread_info_t *ti = (thread_info_t *)arg;
char *result = "INCOMPLETE";
int ok_count;
int err_count;
int last_error_rc;
char task_name[64];
int i, j;
int rc;
do
{
if (ti == NULL)
{
printf("\n%s: Input argument is NULL. Exiting.\n", __FUNCTION__);
break;
}
snprintf(task_name, sizeof(task_name), "check-connect-%d", ti->inst_num);
printf ("[%s] Running Check Connect task instance %d (%d iterations, %d second sleep interval)...\n",
task_name, ti->inst_num, ti->num_iter, ti->sleep_time);
/* Register with OpEN -- Note the use of the 'Threaded' registration API here */
&clientHandle)) != OPEN_E_NONE)
{
printf("[%s] Failed to initialize OpEN RPC connection. Exiting (result = %d)\n", task_name, rc);
break;
}
/* run several iterations of the connectivity test before exiting */
for (i = 0; i < ti->num_iter; i++)
{
ok_count = err_count = last_error_rc = 0;
if (i > 0)
{
sleep(ti->sleep_time);
}
/* OpEN API connectivity test */
for (j = 0; j < MAX_TRIES; j++)
{
rc = openapiConnectivityCheck(&clientHandle);
if (rc == OPEN_E_NONE)
{
ok_count++;
}
else
{
last_error_rc = rc;
err_count++;
}
} /* endfor j */
printf ("[%s] OpEN API test iteration %2d -- Attempts=%d: OK=%d Error=%d (Last Error RC = %d)\n",
task_name, i + 1, j, ok_count, err_count, last_error_rc);
} /* endfor i */
/* Unregister with OpEN */
if ((rc = openapiClientTearDown(&clientHandle)) != OPEN_E_NONE)
{
printf("[%s] Failed to cleanup OpEN RPC connection. Exiting (result = %d)\n", task_name, rc);
break;
}
result = "COMPLETE";
} while (0);
sleep(1);
return strdup(result);
}
/***************************************************************/
int main(int argc, char **argv)
{
openapiClientHandle_t clientHandle;
open_buffdesc switch_os_revision;
char switch_os_revision_string[100];
pthread_attr_t attr;
thread_info_t thread_info[MAX_THREADS];
thread_info_t *ti;
int i;
void *res;
memset(thread_info, 0, sizeof(thread_info));
l7proc_crashlog_register();
/* Register with OpEN -- Note the use of the 'Threaded' registration API in this example */
if ((result = openapiClientRegisterEnhanced("multi_threaded_app_example",
&clientHandle)) != OPEN_E_NONE)
{
printf("\nFailed to initialize RPC to OpEN. Exiting result = %d\n", result);
return 1;
}
/* RPC call can fail until server starts. Keep trying */
while (openapiConnectivityCheck(&clientHandle) != OPEN_E_NONE)
{
sleep(1);
}
L7PROC_LOGF (L7PROC_LOG_SEVERITY_INFO, 0, "Starting Multi-Threaded App example application");
printf("\n");
switch_os_revision.pstart = switch_os_revision_string;
switch_os_revision.size = sizeof(switch_os_revision_string);
if (openapiNetworkOSVersionGet(&clientHandle, &switch_os_revision) == OPEN_E_NONE)
{
printf("Network OS version = %s\n", switch_os_revision_string);
}
else
{
printf("Network OS version retrieve error\n");
}
printf("Starting %d process threads...\n", (int)MAX_THREADS);
/* instantiate multiple threads within this application process */
pthread_attr_init(&attr);
for (i = 0, ti = &thread_info[i]; i < MAX_THREADS; i++, ti++)
{
ti->inst_num = i + 1;
ti->num_iter = MAX_ITER;
ti->sleep_time = MIN_SLEEP + (i * 2);
pthread_create(&ti->thread_id, &attr, check_connect_task, ti);
}
pthread_attr_destroy(&attr);
/* join each thread to display its returned value upon termination */
for (i = 0, ti = &thread_info[i]; i < MAX_THREADS; i++, ti++)
{
pthread_join(ti->thread_id, &res);
printf("Thread instance %d exited.", ti->inst_num);
if (res != NULL)
{
printf(" Status: %s", (char *)res);
free(res);
}
printf("\n");
}
printf("All process threads have completed. Exiting application.\n\n");
/* Log goodbye message */
L7PROC_LOGF(L7PROC_LOG_SEVERITY_INFO, 0, "Stopping Multi-Threaded App example application");
(void) openapiClientTearDown(&clientHandle);
return 0;
}