⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 labview_test_controller.cpp

📁 最新的版本ACE-5.6.8,刚从外文网上搬下,与大家分享.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// $Id: labview_test_controller.cpp 81007 2008-03-18 20:47:11Z shuston $
//
// Defines the entry point for the LabVIEW RT test controller DLL application.
// This DLL is loaded at system boot by LabVIEW RT. The controller waits for
// TCP connections from the ACE+TAO test scripts. The test scripts will direct
// operation of the tests via commands sent over TCP. In order to be ready for
// connections without intervention via VI, the initial load will spawn a
// thread that sets up the listening socket.

#include "stdafx.h"
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <memory.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <Winsock2.h>

// NULL is the documented way to check DLL handles, and this is plain
// Windows code, not ACE, so we stick to the Microsoft way...
// FUZZ: disable check_for_NULL

// This is plain Windows code, not ACE. Therefore we disable 
// the check for ACE_OS
// FUZZ: disable check_for_lack_ACE_OS

// TEST_FUNC is the prototype for the called test's main entrypoint. It's
// the normal C main.
typedef int (*TEST_FUNC) (int argc, char *argv[]);

// Thread entrypoints
static unsigned int __stdcall test_control (void *param);
static unsigned int __stdcall peer_svc (void *peer_p);
static unsigned int __stdcall run_test (void *test_p);

static const char *format_errmsg (unsigned int errcode, const char *prefix);

// Logging information
static const char *LogName = "acetao.log";
static HANDLE logf = INVALID_HANDLE_VALUE;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                      )
{
  if (ul_reason_for_call == DLL_PROCESS_ATTACH)
    {
      return (0 != _beginthreadex (0,            // security
                                   8 * 1024,     // stack size
                                   test_control, // entrypoint
                                   0,            // param
                                   0,            // creation flags
                                   0));          // ptr to thread id
    }

  return TRUE;
}

class Test
{
public:
  Test () : dll_handle_ (NULL),
            thr_handle_ (0),
            entry_ (0),
            running_ (false),
            status_ (-1)
    {}
  ~Test ();

  HANDLE handle (void) { return this->thr_handle_; }
  int run (void);
  const char *start (const char *name);
  bool status (int *exit_status);
  int wait (void);
  void kill (void);

  // Clean up remnants of a test run.
  void cleanup (void);

private:
  HMODULE dll_handle_;
  HANDLE thr_handle_;
  TEST_FUNC entry_;
  bool running_;
  int status_;
  enum { CMDLINE_LEN = 1024, ARGV_SIZE = 100 };
  char name_[CMDLINE_LEN];
  char cmdline_[CMDLINE_LEN];
  int argc_;
  char *argv_[ARGV_SIZE];
};

class Peer
{
public:
  Peer (SOCKET h) : handle_ (h) {}

  // Run the Peer's session; intended to be called from a new thread devoted
  // to this peer's session.
  int svc (void);

private:
  Peer () {};

  // Process command input from socket.
  int command (void);

  // Send a reply string to the peer.
  int reply (const char *msg);

  SOCKET handle_;
  Test test_;
};

// Run a peer session; assume there's a thread for each session, so this
// object has all it needs for context located in 'this' object, and it can
// block at any point as long as one remembers that there is one or more
// test threads running and some attention must be paid to the encapsulated
// socket handle over which this object receives control commands from the
// host test driver.
int
Peer::svc (void)
{
  // Read commands until EOF (peer closed) or protocol error
  while (0 == this->command ())
    ;
  closesocket (this->handle_);
  this->handle_ = INVALID_SOCKET;
  return 0;
}

int
Peer::command (void)
{
  // The protocol exchanges with the peer are execpted to be lock-step
  // request-reply command lines, so we can make assumptions about a complete
  // line being available to make life easier.
  const int MAX_RECV = 1024;
  char line[MAX_RECV], *p;
  p = &line[0];
  int count = 0, len = 0;
  while ((count = recv (this->handle_, p, MAX_RECV - len, 0)) > 0)
    {
      p[count] = '\0';
      len += count;
      p += count;
      char *nl;
      if ((nl = strchr (line, '\n')) == 0)
        continue;

      // At this point we have a 0-terminated string with a newline ending
      // the command line. Break out and process the command.
      break;
    }
  if (count <= 0)
    return -1;         // Relay closed/error socket to caller

  char *cmd = strtok (line, "\t \n\r");
  if (cmd == 0)
    {
      char err[1024];
      sprintf (err, "Can't parse input: %s\n", line);
      this->reply (err);
      return -1;
    }
  // Which command is it? These commands are known:
  //
  //   run <test-dll> [args]
  //     Run test in the named test-dll; respond with "OK" or an error string.
  //   status
  //     If test still running return "RUNNING" else return exit status.
  //   wait
  //     Wait for test to exit; return "OK"
  //   kill
  //     Kill the thread with the most recent test; return "OK".
  //   snaplog
  //     Take a snapshot of the current stdout/stderr log to a new file
  //     name and reset the stdout/stderr log.
  if (strcmp ("run", cmd) == 0)
    {
      char *test = strtok (0, "\t \n\r");
      if (test == 0)
        {
          this->reply ("Malformed run command\n");
          return -1;
        }
      // start() pulls apart the rest of the command line...
      const char *errmsg = this->test_.start (test);
      if (errmsg == 0)
        this->reply ("OK\n");
      else
        this->reply (errmsg);
    }
  else if (strcmp ("status", cmd) == 0)
    {
      int status;
      if (this->test_.status (&status))
        {
          char retvalmsg[64];
          sprintf (retvalmsg, "%d\n", status);
          this->reply (retvalmsg);
        }
      else
        this->reply ("RUNNING\n");
    }
  else if (strcmp ("wait", cmd) == 0)
    {
      int status = this->test_.wait ();
      char retvalmsg[64];
      sprintf (retvalmsg, "%d\n", status);
      this->reply (retvalmsg);
    }
  else if (strcmp ("kill", cmd) == 0)
    {
      // Killing things is bad... say we can't and the host should reboot us.
      this->reply ("NO - please reboot me\n");
    }
  else if (strcmp ("waitforfile", cmd) == 0)
    {
      char *name = strtok (0, "\t \n\r");
      if (name == 0)
        {
          this->reply ("Malformed waitforfile command\n");
          return -1;
        }
      char *secs_s = strtok (0, "\t \n\r");
      int secs = 0;
      if (secs_s == 0 || (secs = atoi (secs_s)) <= 0)
        {
          this->reply ("Malformed waitforfile command\n");
          return -1;
        }
      struct _stat info;
      const char *msg = 0;
      bool found = false;
      while (secs > 0)
        {
          if (_stat (name, &info) == -1)   // No file yet
            {
              if (errno != ENOENT)
                {
                  // Something more serious than no file yet; bail out.
                  msg = format_errmsg (errno, name);
                  break;
                }
            }
          else
            {
              if (info.st_size > 0)
                {
                  found = true;
                  break;
                }
            }
          // Either no file yet, or it's there but with no content yet.
          Sleep (1 * 1000);     // arg is in msec
          --secs;
        }
      if (found)
        this->reply ("OK\n");
      else if (secs == 0)
        this->reply ("TIMEOUT\n");
      else
        this->reply (msg);
    }
  else if (strcmp ("snaplog", cmd) == 0)
    {
      if (logf == INVALID_HANDLE_VALUE)
        {
          this->reply ("NONE\n");
        }
      else
        {
          CloseHandle (logf);
          if (0 == rename (LogName, "snapshot.txt"))
            {
              char abspath[1024];
              if (_fullpath (abspath, "snapshot.txt", 1024))
                {
                  strcat (abspath, "\n");
                  this->reply (abspath);
                }
              else
                {
                  // Last ditch effort to get a name back to the client
                  this->reply ("\\ni-rt\\system\\snapshot.txt\n");
                }
            }
          else
            {
              this->reply ("NONE\n");
            }
          // Reset stdout/stderr to a new file
          logf = CreateFile (LogName,
                             FILE_ALL_ACCESS,
                             FILE_SHARE_READ,
                             0,    // security
                             CREATE_ALWAYS,
                             FILE_ATTRIBUTE_NORMAL,
                             0);
          SetStdHandle (STD_OUTPUT_HANDLE, logf);
          SetStdHandle (STD_ERROR_HANDLE, logf);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -