mms_api.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <mms.h>
#include <mgmt_mms.h>
#define MMS_API_MSG "message task [\"3999\"] who [operator] \
severity [error] %s; "
#if mms_lint
struct timeval *_RESTRICT_KYWD);
#define select mms_select_large_fdset
#endif
/*
* mms_serr()
*
* Parameters:
* - severity The severity of the system error encountered
* - file The name of the file in which the error occurred
* - line The line number in the file where the error occurred
* - fmt The format of the message to be mms_printed.
* - ... The variable number of arguments for the message.
*
* This function is used within the MMS API to handle system errors that
* are not recoverable from. The function outputs the critial message to
* the mms_trace file and then aborts. This function is used to handle
* system errors such as thread function errors.
*
* Return Values:
* None
*
*/
void
{
abort();
}
#define MMS_API_ERR_FMT "response task [\"%s\"] error [%s %s] %s;"
#define MMS_API_MSG_PAD 30
/*
* mms_gen_err_rsp()
*
* Parameters:
* - tid The task id of the command to receive error response
* - code The code to use in the error response
* - err_msg The error message to use in the error response
*
* This function is used within the MMS API to generate an error response.
* This is only used in the mms_api_reader to send a generated error
* response to async commands waiting for a response. This is done
* when the API has an internal processing error that it cannot recover
* from
*
* Return Values:
* The generated error response if it could create it or NULL
*
*/
{
char *err_rsp;
char *s_internal;
char *s_code;
int len = MMS_API_MSG_PAD;
}
if (err_msg)
if (!err_rsp) {
}
/* Should never occur unless error response format */
/* has a syntax error or the parser cannot obtain */
/* memory for the parse tree */
"during generation of error response:\n%s", err_rsp);
"mms_mmp_parse, line %d, col %d, "
"near token \"%s\", err code %d, %s",
}
return (rsp);
}
return (rsp);
}
/*
* mms_msglen
*
* Calculate the message length.
*/
static int
{
char *ap;
int len = MMS_API_MSG_PAD;
int i;
for (i = 0; i < nargs; i++) {
}
return (len);
}
/*
* mms_crtmsg
*
* Create an error response message.
*/
static char *
{
char *msg;
return (NULL);
return (NULL);
}
return (msg);
}
/*
* mms_errmsg
*
* Allocate the memory for and then create and return an
* error message.
*/
static char *
{
char *message;
int len;
/*
* Create the error message.
*/
return (message);
}
/*
* mms_log_error
*
* Output an error message to a log file.
*/
static void
{
char *lmsg;
char *err_msg;
int len = MMS_API_MSG_PAD;
return;
return;
if (!err_msg) {
return;
}
"message:\n%s", message);
}
/*
* Should never occur unless message format has a syntax
* error or the parser cannot obtain memory for the parse
* tree.
*/
"during generation of message:\n%s", message);
"mms_log_error: mms_mmp_parse, line %d, "
"col %d, near token \"%s\", err code %d, %s",
}
"message to clients log");
return;
}
} else {
"message to client's log");
}
}
/*
* mms_send_errmsg()
*
* Parameters:
* - session Connection to MMS to use.
* - message The mms api error message to log to client
*
* This function will log a error that is internal to MMS into the
* clients log file if it is enabled. The message is in the mms catalog
* and thus will be internationalized. If any type of error is encountered,
* the message itself will be outputed to the log file.
*
* Return Values:
* - None
*
*/
void
{
char *message;
int len;
return;
/*
* Calculate the message length.
*/
if (!message)
return;
"client's log file:\n%s", message);
}
/*
* mms_rsp_extract
*
* Extract the command, command type, and tag from the response.
*
* Return:
* 0 Successful
* > 0 API Error
* < 0 Response specific error
*/
int
{
"detected on MMS input:\n%s", input);
if (err) {
"mms_rsp_extract: mms_mmp_parse, line "
"%d, col %d, near token \"%s\", err code %d, %s",
}
/* XXX SEE IF LM PARSE MMS_ERROR CODE CAN BE ADAPTED TO WORK HERE AS WELL */
return (MMS_E_INVALID_RESPONSE);
}
"node found in what should be a valid "
"response or event from MMS:\n%s", input);
"command node");
return (MMS_E_INVALID_RESPONSE);
}
/*
* Validate the response.
*/
"response or event input from MMS:\n%s", input);
return (-1);
}
/*
* Process an event.
*/
"event from MMS:\n%s", input);
"clause found in event:\n%s", input);
return (-1);
}
"string found in event:\n%s", input);
return (-1);
}
/*
* Process an unacceptable response.
*/
"unaccept response from MMS");
/*
* Process all other response types.
*/
} else {
"from MMS:\n%s", input);
"clause found in response:\n%s", input);
"task id clause", "task id clause");
return (MMS_MISSING_TASKID);
}
"string found in response:\n%s", input);
"task id string", "task id string");
return (MMS_MISSING_TASKID);
}
/*
* Determine the response type.
*/
!= NULL) {
"accept response");
"success response");
"intermediate response");
"error response");
"cancelled response");
} else {
"unknown type of response:\n%s", input);
return (MMS_INVALID_RSP);
}
}
return (0);
}
/*
* mms_rsp_read
*
* Wait for and read a response from the MM.
*
* Return:
* 0 Successful
* > 0 API Error
* < 0 Response specific error
*/
int
{
int resp_type = 0;
int rc;
/* LINTED warning: constant in conditional context */
while (1) {
"API session is being terminated");
return (MMS_API_SHUTDOWN);
}
" of error, returning error response for command");
return (sp->mms_api_errcode);
}
if (rc < 0) {
continue;
continue;
"Socket to MMS is not open");
return (MMS_E_NET_IO_ERR);
} else {
return (MMS_SELECT_ERROR);
}
} else if (rc == 0) { /* select timeout hit */
continue;
} else { /* something to read on socket */
break;
}
}
/*
* Obtain next response from mm.
*/
if (rc == 0) {
"disconnected from client");
} else {
"to read new response, rc - %d", rc);
}
MMS_API_3013_MSG, 0);
return (MMS_E_NET_IO_ERR);
}
/*
* Extract the command, type and tag from the data.
*/
if (rc) {
return (rc);
}
/*
* Create the response structure.
*/
return (0);
}
/*
* mms_obtain_accept
*
* Wait for and then process an accept response.
*/
int
{
int rc = MMS_API_OK;
int c;
"response, tid - %s", tid);
"accept mutex failed with errno - %s", strerror(c));
}
/* LINTED warning: constant in conditional context */
while (1) {
"session is being terminated");
break;
}
/*
* Check to see if MMS API has encountered an
* internal processing error.
*/
"a state of error, returning an error response "
"for command with task id %s", tid);
break;
}
/*
*/
"id of accept response, %s, and task id of "
"last command sent to MMS, %s, do not "
}
break;
}
/*
* Wait for the accept response, becoming the socket
* reader if no thread is currently reading from socket.
*/
!= 0) {
"Unlock of MMS accept mutex failed "
"with errno - %s", strerror(c));
}
!= 0) {
" MMS accept mutex failed with errno - %s",
strerror(c));
}
if (rc != MMS_API_OK)
break;
} else {
&sp->mms_acc_mutex)) != 0) {
"Unable to wait on accept condition"
" variable, errno - %s", strerror(c));
}
}
"by broadcast from reader thread to look for a accept "
"response, tid - %s", tid);
}
"accept mutex failed with errno - %s", strerror(c));
}
return (rc);
}
/*
* mms_obtain_event()
*
* This function obtains an event that has been sent by the MM.
*
* Return Values:
* MMS_API_OK If an event was obtained from MMS.
* ! MMS_API_OK If an error occurred during processing.
*
*/
int
{
int err;
int rc;
"mms_obtain_event: Session pointer is set to "
"NULL, unable to obtain any events at this time");
return (MMS_WRONG_API_MODE);
}
}
/* LINTED constant in conditional context */
while (1) {
"session is being terminated");
break;
}
"state of error, unable to obtain any events "
"at this time");
break;
}
/*
* Check for a queued event.
*/
"mms_obtain_event: Found event with %s"
rc = MMS_API_OK;
break;
}
/*
* Did not find a event for thread.
*/
"mms_obtain_event: No event waiting, check if "
"any thread is reading from socket to MM");
/*
* If no thread reading from MM, become reader thread.
*/
!= 0) {
"of MMS event list mutex failed with errno"
}
&rsp);
return (rc);
} else {
"already exists, going into wait");
&sp->mms_ev_mutex)) != 0) {
"MMS event condition variable failed with "
}
}
"by broadcast from reader thread");
}
}
return (rc);
}
/*
* mms_obtain_final
*
* Wait for and then process a final response.
*/
int
{
int rc;
int c;
"response, tid - %s", tid);
"response mutex failed with errno - %s", strerror(c));
}
/* LINTED warning: constant in conditional context */
while (1) {
"session is being terminated");
break;
}
/*
* Check to see if MMS API has encountered an
* internal processing error.
*/
"a state of error, returning an error response "
"for command with task id %s", tid);
break;
}
/*
* Go through response list to see if a final
* response for the specified command exists.
*/
rc = MMS_API_OK;
break;
}
/*
* Wait for the final response, becoming the socket
* reader if no thread is currently reading from socket.
*/
!= 0) {
"Unlock of MMS wait response mutex failed "
"with errno - %s", strerror(c));
}
!= 0) {
"Lock of MMS wait response mutex failed "
"with errno - %s", strerror(c));
}
break;
} else {
&sp->mms_rsp_mutex)) != 0) {
"Unable to wait on accept condition"
" variable, errno - %s", strerror(c));
}
}
"by broadcast from reader thread to look for a final "
"response, tid - %s", tid);
}
"response mutex failed with errno - %s", strerror(c));
}
return (rc);
}
/*
* mms_send
*
* Send a command and wait for an accept.
*/
int
mms_rsp_ele_t **rsp)
{
int cmdlen;
int rc;
int c;
/*
* A response is returned on synchronous requests.
*/
if (rsp)
/*
* Only one begin-end command sequence may be pending at a time,
* If this is a 'begin' command or a command sent synchronously,
* wait for any pending command sequences to complete before
* allowing this command to be sent.
*/
}
/*
* Stop other clients from sending commands until this
* client receives an accept or unaccept to this command.
*/
"accept mutex failed with errno - %s", strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
/*
* Write the command to the socket.
*/
"connection mutex failed with errno - %s", strerror(c));
}
"command accept mutex failed with errno - %s",
strerror(c));
}
return (MMS_E_NET_IO_ERR);
}
/*
* Wait for an accept response.
*/
if (rc == MMS_API_OK) {
*rsp = (void *)rsp_accept;
} else {
}
}
"accept mutex failed with errno - %s", strerror(c));
}
if (cmdtype == MMS_CMD_END ||
}
return (rc);
}
/*
* mms_sync_reader
*
* Wait for and then process data written to the socket.
*/
int
{
char *msg;
int rc;
int c;
tid);
/* LINTED warning: constant in conditional context */
while (1) {
/*
* Wait for data to be written to the socket.
*/
if (rc > 0) {
break;
} else if (rc < 0) {
continue;
}
/*
* Process an event response. Add the event to the
* event list is there is an registration for the event.
*/
/*
* If waiting for events, return this event.
* Otherwise, queue the response and signal
* the waiting thread.
*/
if (wait_type == MMS_API_RSP_EVENT) {
break;
} else {
}
/*
*/
if (wait_type == MMS_API_RSP_ACC)
break;
/*
* Process a final response.
*/
if ((wait_type == MMS_API_RSP_FINAL) &&
"final response for itself, tid %s", tid);
break;
}
}
}
if (rc == MMS_API_OK) {
} else {
if (rc == MMS_API_SHUTDOWN)
else
}
/*
* Unlock and wakeup up threads waiting for a response to be
* read. This will allow another thread to become the reader.
*/
"mutex failed with errno - %s", strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
/*
* Release the reader lock.
*/
"mutex failed with errno - %s", strerror(c));
}
/*
* Wake-up threads waiting on read. Another thread must
* become the reader if waiting for a response.
*/
"response condition variable failed with errno - %s",
strerror(c));
}
"response condition variable failed with errno - %s",
strerror(c));
}
"accept condition variable failed with errno - %s",
strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
"mutex failed with errno - %s", strerror(c));
}
return (rc);
}
/*
* mms_api_reader()
*
* Parameters:
* - arg The structure used to access the session to MMS
*
* The mms_async_init() starts this function as a standalone thread.
* This thread reads input on behalf of a client connect to the MMS
* and final command responses as well as unsolictied events that the client
* has registered for.
*
* Return Values:
* None
*
*/
void *
mms_api_reader(void *arg)
{
char *msg;
char *tid;
int rc;
/*
* Lock the reading thread. The API reader thread should
* always hold this lock.
*/
"MMS reading mutex, reader thread exiting");
/* log msg, set state, any wakeup */
return ((void *)NULL);
}
/*
* Reader thread ready for requests.
*/
/*
* Update the thread count.
*/
/*
* Wait for input from the MMS socket and process the response.
*/
/* LINTED warning: constant in conditional context */
while (1) {
/*
* Wait for a response from the MM.
*/
if (rc > 0) {
break;
} else if (rc < 0) {
continue;
}
/*
* Process an event response.
*/
new_rsp);
} else {
}
/*
* Process an accept response.
*/
/*
* Process an unaccept response.
*/
rc = MMS_API_ERR;
break;
}
}
/*
* Process a final response.
*/
/*
* Find the command in the command list.
*/
break;
}
"mms_api_reader: Final response is for"
new_rsp);
} else {
}
/*
* An invalid response was received.
*/
} else {
break;
}
}
/*
* An unrecoverable error occurred. Terminate processing
* and wakeup any threads waiting for responses.
*/
}
if (msg)
return (0);
}