Logo Search packages:      
Sourcecode: gsoap version File versions

mtmagicserver.cpp

//    mtmagicserver.cpp
//    Multi-threaded magic squares server
//    Runs as CGI (not multi-threaded) or multi-threaded standalone
//    Computation of the magic square has been deliberately slowed down to
//    demonstrate work load issues (see SLEEP constant)

// Run from the command line with arguments IP (which must be the
// IP of the current machine you are using) and PORT to run this as a
// multi-threaded stand-alone server on a port. For example:
// > mtmagicserver.cgi 18081
// To let 'magic' client talk to this service, change the URL in code magic.cpp
// into "localhost:18081"

// This example illustrates two alternative server implementations with threads.
// The first implementation recycles gSOAP resources but is bounded to a maximum
// number of threads. Each thread needs to be joined, so runaway processes will
// halt the server at some point.
// The second implementation has no thread limitation. Runaway threads are not
// controlled.

#include "soapH.h"
#include "magic.nsmap"
#include <unistd.h>     // import sleep()
#include <pthread.h>

#define BACKLOG (100)   // Max. request backlog
#define MAX_THR (8)     // Max. threads to serve requests
#define SLEEP     (0)   // use this to make each thread sleep to mimic work load latency

////////////////////////////////////////////////////////////////////////////////
//
//    Multi-Threaded Magic Squares Server
//
////////////////////////////////////////////////////////////////////////////////

void *process_request(void*);

int main(int argc, char **argv)
{ struct soap soap;
  soap_init(&soap);
  // soap.accept_timeout = 60; // die if no requests are made within 1 minute
  if (argc < 2)         // no args: assume this is a CGI application
  { soap_serve(&soap);  // serve request
    soap_destroy(&soap);// cleanup class instances
    soap_end(&soap);    // cleanup
  }
  else
  { pthread_t tid;
    int port;
    int m, s, i;
    port = atoi(argv[1]);
    m = soap_bind(&soap, NULL, port, BACKLOG);
    if (m < 0)
    { soap_print_fault(&soap, stderr);
      exit(1);
    }
    fprintf(stderr, "Socket connection successful %d\n", m);
    for (i = 0; ; i++)
    { s = soap_accept(&soap);
      if (s < 0)
      { if (soap.errnum)
          soap_print_fault(&soap, stderr);
      else
        fprintf(stderr, "Server timed out\n");
        break;
      }
      fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
      pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)soap_copy(&soap));
    }
  }
  soap_done(&soap);
  return 0;
}

void *process_request(void *soap)
{ pthread_detach(pthread_self());
  soap_serve((struct soap*)soap);
  soap_destroy((struct soap*)soap);
  soap_end((struct soap*)soap);
  soap_done((struct soap*)soap);
  free(soap);
  return NULL;
}

////////////////////////////////////////////////////////////////////////////////
//
//    Magic Square Algorithm
//
////////////////////////////////////////////////////////////////////////////////

int ns1__magic(struct soap *soap, int n, matrix *square)
{ int i, j, k, l, key = 2;
  if (n < 1)
    return soap_sender_fault(soap, "Negative or zero size", "<error xmlns=\"http://tempuri.org/\">The input parameter must be positive</error>");
  if (n > 100)
    return soap_sender_fault(soap, "size > 100", "<error xmlns=\"http://tempuri.org/\">The input parameter must not be too large</error>");
  square->resize(n, n);
  for (i = 0; i < n; i++)
    for (j = 0; j < n; j++)
      (*square)[i][j] = 0;
  i = 0;
  j = (n-1)/2;
  (*square)[i][j] = 1;
  while (key <= n*n)
  { if (i-1 < 0)
      k = n-1;
    else
      k = i-1;
    if (j-1 < 0)
      l = n-1;
    else
      l = j-1;
    if ((*square)[k][l])
      i = (i+1) % n;
    else
    { i = k;
      j = l;
    }
    (*square)[i][j] = key;
    key++;
  }
  sleep(SLEEP);         // mimic work load latency
  return SOAP_OK;
}

////////////////////////////////////////////////////////////////////////////////
//
//    Class vector Methods
//
////////////////////////////////////////////////////////////////////////////////

vector::vector()
{ __ptr = 0;
  __size = 0;
}

vector::vector(int n)
{ __ptr = (int*)soap_malloc(soap, n*sizeof(int));
  __size = n;
}

vector::~vector()
{ soap_unlink(soap, this); // not required, but just to make sure if someone calls delete on this
}

void vector::resize(int n)
{ int *p;
  if (__size == n)
    return;
  p = (int*)soap_malloc(soap, n*sizeof(int));
  if (__ptr)
  { for (int i = 0; i < (n <= __size ? n : __size); i++)
      p[i] = __ptr[i];
    soap_unlink(soap, __ptr);
    free(__ptr);
  }
  __size = n;
  __ptr = p;
}

int& vector::operator[](int i) const
{ if (!__ptr || i < 0 || i >= __size)
    fprintf(stderr, "Array index out of bounds\n");
  return __ptr[i];
}

////////////////////////////////////////////////////////////////////////////////
//
//    Class matrix Methods
//
////////////////////////////////////////////////////////////////////////////////

matrix::matrix()
{ __ptr = 0;
  __size = 0;
}

matrix::matrix(int rows, int cols)
{ __ptr = soap_new_vector(soap, rows);
  for (int i = 0; i < cols; i++)
    __ptr[i].resize(cols);
  __size = rows;
}

matrix::~matrix()
{ soap_unlink(soap, this); // not required, but just to make sure if someone calls delete on this
}

void matrix::resize(int rows, int cols)
{ int i;
  vector *p;
  if (__size != rows)
  { if (__ptr)
    { p = soap_new_vector(soap, rows);
      for (i = 0; i < (rows <= __size ? rows : __size); i++)
      { if (this[i].__size != cols)
          (*this)[i].resize(cols);
      (p+i)->__ptr = __ptr[i].__ptr;
      (p+i)->__size = cols;
      }
      for (; i < rows; i++)
        __ptr[i].resize(cols);
    }
    else
    { __ptr = soap_new_vector(soap, rows);
      for (i = 0; i < rows; i++)
        __ptr[i].resize(cols);
      __size = rows;
    }
  }
  else
    for (i = 0; i < __size; i++)
      __ptr[i].resize(cols);
}

vector& matrix::operator[](int i) const
{ if (!__ptr || i < 0 || i >= __size)
    fprintf(stderr, "Array index out of bounds\n");
  return __ptr[i];
}

Generated by  Doxygen 1.6.0   Back to index