// Svc_Handler_Test.cpp,v 4.21 2004/01/05 22:57:06 shuston Exp

// ============================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    Svc_Handler_Test.cpp
//
// = DESCRIPTION
//    This tests illustrates the "buffering" strategy of the
//    <ACE_Buffered_Svc_Handler>.  This test also illustrates how the
//    <ACE_FILE_IO> classes work.
//
// = AUTHORS
//    Douglas C. Schmidt <schmidt@cs.wustl.edu>
//
// ============================================================================

#include "test_config.h"
#include "ace/OS_NS_string.h"
#include "ace/FILE_Connector.h"
#include "ace/Null_Condition.h"
#include "ace/Null_Mutex.h"
#include "ace/Svc_Handler.h"
#include "ace/Synch_Traits.h"

ACE_RCSID(tests, Svc_Handler_Test, "Svc_Handler_Test.cpp,v 4.21 2004/01/05 22:57:06 shuston Exp")

typedef ACE_Buffered_Svc_Handler <ACE_FILE_STREAM, ACE_NULL_SYNCH> SVC_HANDLER;

static void
run_test (SVC_HANDLER &svc_handler,
          size_t iterations)
{
  // Create a whole slew of message blocks and pass them to the
  // <svc_handler>.
  for (size_t i = 0; i < iterations; i++)
    {
      ACE_Message_Block *mb;
      ACE_NEW (mb,
               ACE_Message_Block (sizeof (ACE_LIB_TEXT("hello "))));

      ACE_Message_Block *cb1;
      ACE_NEW (cb1,
               ACE_Message_Block (sizeof (ACE_LIB_TEXT("there\n"))));

      ACE_Message_Block *cb2;
      ACE_NEW (cb2,
               ACE_Message_Block (sizeof (ACE_LIB_TEXT("there\n"))));

      mb->copy ("hello ",
                ACE_OS::strlen (ACE_LIB_TEXT("hello ")));
      cb1->copy ("there ",
                 ACE_OS::strlen (ACE_LIB_TEXT("there ")));
      mb->cont (cb1);
      cb2->copy ("doug\n",
                ACE_OS::strlen (ACE_LIB_TEXT("doug\n")));
      cb1->cont (cb2);

      // Note that this is a buffered call!
      if (svc_handler.put (mb) == -1)
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("%p\n"),
                    ACE_TEXT ("put")));
    }

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("final flush\n")));

  // Make sure to flush everything out before we exit.
  if (svc_handler.flush () == -1)
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("%p\n"),
                ACE_TEXT ("flush")));
}

int
run_main (int argc, ACE_TCHAR *argv[])
{
  ACE_START_TEST (ACE_TEXT ("Svc_Handler_Test"));
  {
    size_t max_buffer_size = BUFSIZ;
    size_t iterations = 10;

    if (argc > 1)
      max_buffer_size = ACE_OS::atoi (argv[1]);
    if (argc > 2)
      iterations = ACE_OS::atoi (argv[2]);

    ACE_FILE_Connector connector;
    ACE_FILE_IO file_io;
    // Create a temporary filename.
    ACE_FILE_Addr file (ACE_sap_any_cast (ACE_FILE_Addr &));

    // Open up the temp file.
    if (connector.connect (file_io, file) == -1)
      ACE_ERROR_RETURN ((LM_ERROR,
                         ACE_TEXT ("connect failed for %p\n"),
                         file.get_path_name ()),
                        1);

#if (!defined (ACE_WIN32) \
     || (defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 == 1)) && \
    !defined (VXWORKS)
# define TEST_CAN_UNLINK_IN_ADVANCE
#endif

    // Create the service handler and assign it <file_io> as its data
    // sink.
    SVC_HANDLER svc_handler (0,
                             0,
                             0,
                             max_buffer_size,
                             0);
    svc_handler.peer () = file_io;

    // Run the test.
    run_test (svc_handler, iterations);

    file_io.close ();

    // Open up the temp file.
    if (connector.connect (file_io, file) == -1)
      ACE_ERROR_RETURN ((LM_ERROR,
                         ACE_TEXT ("connect failed for %p\n"),
                         file.get_path_name ()),
                        1);
    char buf[ACE_MAXLOGMSGLEN + 1];
    ACE_LOG_MSG->clr_flags (ACE_Log_Msg::VERBOSE_LITE);

    ACE_FILE_Info info;
    file_io.get_info (info);
    ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("file size = %d\n"), info.size_));

    for (ssize_t n_bytes; (n_bytes = file_io.recv (buf, ACE_MAXLOGMSGLEN)) > 0; )
      {
        buf[n_bytes] = '\0';
        ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("%s"), ACE_TEXT_CHAR_TO_TCHAR(buf)));
      }

    ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT("\n")));

    file_io.close ();

    if (file_io.unlink () == -1)
      ACE_ERROR_RETURN ((LM_ERROR,
                         ACE_TEXT ("unlink failed for %p\n"),
                         file.get_path_name ()),
                        1);
  }

  ACE_END_TEST;
  return 0;
}

#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Buffered_Svc_Handler <ACE_FILE_STREAM, ACE_NULL_SYNCH>;
template class ACE_Svc_Handler <ACE_FILE_STREAM, ACE_NULL_SYNCH>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Buffered_Svc_Handler <ACE_FILE_STREAM, ACE_NULL_SYNCH>
#pragma instantiate ACE_Svc_Handler <ACE_FILE_STREAM, ACE_NULL_SYNCH>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
