<commit_before>#include "df_font.h"

#include "df_bitmap.h"
#include "df_common.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

// ****************************************************************************
// Glyph
// ****************************************************************************

typedef struct
{
    unsigned startX;
    unsigned startY;
    unsigned runLen;
} EncodedRun;

class Glyph
{
public:
    unsigned m_width;
    int m_numRuns;
    EncodedRun *m_pixelRuns;

	Glyph(int w)
	{
		m_width = w;
	}
};

// ****************************************************************************
// Global variables
// ****************************************************************************

DfFont *g_defaultFont = NULL;

// ****************************************************************************
// Public Functions
// ****************************************************************************

static bool GetPixelFromBuffer(unsigned *buf, int w, int h, int x, int y)
{
    return buf[(h - y - 1) * w + x] > 0;
}

DfFont *FontCreate(char const *fontName, int size, int weight)
{
    if (size < 4 || size > 1000 || weight < 1 || weight > 9)
        return NULL;

    DfFont *tr = new DfFont;
    memset(tr, 0, sizeof(DfFont));

    // Get the font from GDI
    HDC winDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    HDC memDC = CreateCompatibleDC(winDC);
    int scaledSize = -MulDiv(size, GetDeviceCaps(memDC, LOGPIXELSY), 72);
    HFONT fontHandle = CreateFont(scaledSize, 0, 0, 0, weight * 100, false, false, false,
        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        NONANTIALIASED_QUALITY, DEFAULT_PITCH,
        fontName);
    ReleaseAssert(fontHandle != NULL, "Couldn't find Windows font '%s'", fontName);

    // Ask GDI about the font size and fixed-widthness
    SelectObject(memDC, fontHandle);
    TEXTMETRIC textMetrics;
    GetTextMetrics(memDC, &textMetrics);
    tr->charHeight = textMetrics.tmHeight;
    tr->maxCharWidth = textMetrics.tmMaxCharWidth;
    tr->fixedWidth = (textMetrics.tmAveCharWidth == textMetrics.tmMaxCharWidth);

    // Ask GDI about the name of the font
    char nameOfFontWeGot[256];
    GetTextFace(memDC, 256, nameOfFontWeGot);
    ReleaseWarn(strncasecmp(nameOfFontWeGot, fontName, 255) == 0,
        "Attempt to load font '%s' failed.\n"
        "'%s' will be used instead.",
        fontName, nameOfFontWeGot);

    // Create an off-screen bitmap
    BITMAPINFO bmpInfo = { 0 };
    bmpInfo.bmiHeader.biBitCount = 32;
    bmpInfo.bmiHeader.biHeight = tr->charHeight;
    bmpInfo.bmiHeader.biWidth = tr->maxCharWidth;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    UINT *gdiPixels = 0;
    HBITMAP memBmp = CreateDIBSection(memDC, (BITMAPINFO *)&bmpInfo, DIB_RGB_COLORS, (void **)&gdiPixels, NULL, 0);
	HBITMAP prevBmp = (HBITMAP)SelectObject(memDC, memBmp);

    // Allocate enough EncodedRuns to store the worst case for a glyph of this size.
    // Worst case is if the whole glyph is encoded as runs of one pixel. There has
    // to be a gap of one pixel between each run, so there can only be half as many
    // runs as there are pixels.
    unsigned tempRunsSize = tr->charHeight * (tr->maxCharWidth / 2 + 1);
    EncodedRun *tempRuns = new EncodedRun [tempRunsSize];

    // Setup stuff needed to render text with GDI
    SetTextColor(memDC, RGB(255,255,255));
    SetBkColor(memDC, 0);
    RECT rect = { 0, 0, tr->maxCharWidth, tr->charHeight };

    // Run-length encode each ASCII character
    for (int i = 0; i < 256; i++)
	{
        char buf[] = {(char)i};

        // Get the size of this glyph
        SIZE glyphSize;
        GetTextExtentPoint32(memDC, buf, 1, &glyphSize);
//         if (glyphSize.cx > tr->maxCharWidth)
//             tr->maxCharWidth = glyphSize.cx;
//         if (glyphSize.cy > tr->charHeight)
//             tr->charHeight = glyphSize.cy;

        // Ask GDI to draw the character
		ExtTextOut(memDC, 0, 0, ETO_OPAQUE, &rect, buf, 1, 0);

        // Read back what GDI put in the bitmap and construct a run-length encoding
		memset(tempRuns, 0, tempRunsSize);
		EncodedRun *run = tempRuns;
        for (int y = 0; y < tr->charHeight; y++)
		{
            int x = 0;
            while (x < tr->maxCharWidth)
            {
                // Skip blank pixels
                while (!GetPixelFromBuffer(gdiPixels, tr->maxCharWidth, tr->charHeight, x, y))
                {
                    x++;
                    if (x >= tr->maxCharWidth)
                        break;
                }

                // Have we got to the end of the line?
                if (x >= tr->maxCharWidth)
                    continue;

                run->startX = x;
                run->startY = y;
                run->runLen = 0;

                // Count non-blank pixels
                while (GetPixelFromBuffer(gdiPixels, tr->maxCharWidth, tr->charHeight, x, y))
                {
                    x++;
                    run->runLen++;
                    if (x >= tr->maxCharWidth)
                        break;
                }

                run++;
            }
		}

        // Create the glyph to store the encoded runs we've made
		Glyph *glyph = new Glyph(glyphSize.cx);
		tr->glyphs[i] = glyph;

		// Copy the runs into the glyph
		glyph->m_numRuns = run - tempRuns;
		glyph->m_pixelRuns = new EncodedRun [glyph->m_numRuns];
		memcpy(glyph->m_pixelRuns, tempRuns, glyph->m_numRuns * sizeof(EncodedRun));
	}

	delete [] tempRuns;

	// Release the GDI resources
    DeleteDC(winDC);
    DeleteDC(memDC);
	DeleteObject(fontHandle);
	DeleteObject(memBmp);
	DeleteObject(prevBmp);

    return tr;
}

static int DrawTextSimpleClipped(DfFont *tr, DfColour col, DfBitmap *bmp, int _x, int y, char const *text)
{
    int x = _x;
    DfColour *startRow = bmp->pixels + y * (int)bmp->width;
    int width = bmp->width;

    if (y + tr->charHeight < 0 || y > (int)bmp->height)
        return 0;

    while (*text != '\0')
    {
        if (x + tr->maxCharWidth > (int)bmp->width)
            break;

        unsigned char c = *((unsigned char const *)text);
        Glyph *glyph = tr->glyphs[c];
        EncodedRun *rleBuf = glyph->m_pixelRuns;
        for (int i = 0; i < glyph->m_numRuns; i++)
        {
            int y3 = y + rleBuf->startY;
            if (y3 >= 0 && y3 < (int)bmp->height)
            {
                DfColour *thisRow = startRow + rleBuf->startY * width;
                for (unsigned i = 0; i < rleBuf->runLen; i++)
                {
                    int x3 = x + rleBuf->startX + i;
                    if (x3 >= 0 && x3 < width)
                        thisRow[x3] = col;
                }
            }
            rleBuf++;
        }

        x += glyph->m_width;
        text++;
    }

    return _x - x;
}

int DrawTextSimple(DfFont *tr, DfColour col, DfBitmap *bmp, int _x, int y, char const *text)
{
    int x = _x;
    int width = bmp->width;

    if (x < 0 || y < 0 || (y + tr->charHeight) > (int)bmp->height)
        return DrawTextSimpleClipped(tr, col, bmp, _x, y, text);

    DfColour *startRow = bmp->pixels + y * bmp->width;
    while (*text != '\0')
    {
        unsigned char c = *((unsigned char const *)text);
        if (x + tr->glyphs[c]->m_width > (int)bmp->width)
            break;

        // Copy the glyph onto the stack for better cache performance. This increased the
        // performance from 13.8 to 14.4 million chars per second. Madness.
        Glyph glyph = *tr->glyphs[(unsigned char)*text];
        EncodedRun *rleBuf = glyph.m_pixelRuns;
        for (int i = 0; i < glyph.m_numRuns; i++)
        {
            DfColour *startPixel = startRow + rleBuf->startY * width + rleBuf->startX + x;

            // Loop unrolled for speed
            switch (rleBuf->runLen)
            {
            case 8: startPixel[7] = col;
            case 7: startPixel[6] = col;
            case 6: startPixel[5] = col;
            case 5: startPixel[4] = col;
            case 4: startPixel[3] = col;
            case 3: startPixel[2] = col;
            case 2: startPixel[1] = col;
            case 1: startPixel[0] = col;
                break;
            default:
                for (unsigned i = 0; i < rleBuf->runLen; i++)
                    startPixel[i] = col;
            }
            rleBuf++;
        }

        x += glyph.m_width;
        text++;
    }

    return _x - x;
}

int DrawTextLeft(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);
    return DrawTextSimple(tr, c, bmp, x, y, buf);
}

int DrawTextRight(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);

    int width = GetTextWidth(tr, buf);
    return DrawTextSimple(tr, c, bmp, x - width, y, buf);
}

int DrawTextCentre(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);

    int width = GetTextWidth(tr, buf);
    return DrawTextSimple(tr, c, bmp, x - width/2, y, buf);
}

int GetTextWidth(DfFont *tr, char const *text, int len)
{
	len = IntMin((int)strlen(text), len);
	if (tr->fixedWidth)
	{
		return len * tr->maxCharWidth;
	}
	else
	{
        int width = 0;
        for (int i = 0; i < len; i++)
            width += tr->glyphs[(int)text[i]]->m_width;

		return width;
	}
}
<commit_msg>Bug fix - DrawTextSimple() returned the wrong result. Also removed a pointless loop-unrolling that didn't make any speed difference when I benchmarked it today (on my i3 NUC, in a MSVC 2013 32-bit build).<commit_after>#include "df_font.h"

#include "df_bitmap.h"
#include "df_common.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

// ****************************************************************************
// Glyph
// ****************************************************************************

typedef struct
{
    unsigned startX;
    unsigned startY;
    unsigned runLen;
} EncodedRun;

class Glyph
{
public:
    unsigned m_width;
    int m_numRuns;
    EncodedRun *m_pixelRuns;

	Glyph(int w)
	{
		m_width = w;
	}
};

// ****************************************************************************
// Global variables
// ****************************************************************************

DfFont *g_defaultFont = NULL;

// ****************************************************************************
// Public Functions
// ****************************************************************************

static bool GetPixelFromBuffer(unsigned *buf, int w, int h, int x, int y)
{
    return buf[(h - y - 1) * w + x] > 0;
}

DfFont *FontCreate(char const *fontName, int size, int weight)
{
    if (size < 4 || size > 1000 || weight < 1 || weight > 9)
        return NULL;

    DfFont *tr = new DfFont;
    memset(tr, 0, sizeof(DfFont));

    // Get the font from GDI
    HDC winDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    HDC memDC = CreateCompatibleDC(winDC);
    int scaledSize = -MulDiv(size, GetDeviceCaps(memDC, LOGPIXELSY), 72);
    HFONT fontHandle = CreateFont(scaledSize, 0, 0, 0, weight * 100, false, false, false,
        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        NONANTIALIASED_QUALITY, DEFAULT_PITCH,
        fontName);
    ReleaseAssert(fontHandle != NULL, "Couldn't find Windows font '%s'", fontName);

    // Ask GDI about the font size and fixed-widthness
    SelectObject(memDC, fontHandle);
    TEXTMETRIC textMetrics;
    GetTextMetrics(memDC, &textMetrics);
    tr->charHeight = textMetrics.tmHeight;
    tr->maxCharWidth = textMetrics.tmMaxCharWidth;
    tr->fixedWidth = (textMetrics.tmAveCharWidth == textMetrics.tmMaxCharWidth);

    // Ask GDI about the name of the font
    char nameOfFontWeGot[256];
    GetTextFace(memDC, 256, nameOfFontWeGot);
    ReleaseWarn(strncasecmp(nameOfFontWeGot, fontName, 255) == 0,
        "Attempt to load font '%s' failed.\n"
        "'%s' will be used instead.",
        fontName, nameOfFontWeGot);

    // Create an off-screen bitmap
    BITMAPINFO bmpInfo = { 0 };
    bmpInfo.bmiHeader.biBitCount = 32;
    bmpInfo.bmiHeader.biHeight = tr->charHeight;
    bmpInfo.bmiHeader.biWidth = tr->maxCharWidth;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    UINT *gdiPixels = 0;
    HBITMAP memBmp = CreateDIBSection(memDC, (BITMAPINFO *)&bmpInfo, DIB_RGB_COLORS, (void **)&gdiPixels, NULL, 0);
	HBITMAP prevBmp = (HBITMAP)SelectObject(memDC, memBmp);

    // Allocate enough EncodedRuns to store the worst case for a glyph of this size.
    // Worst case is if the whole glyph is encoded as runs of one pixel. There has
    // to be a gap of one pixel between each run, so there can only be half as many
    // runs as there are pixels.
    unsigned tempRunsSize = tr->charHeight * (tr->maxCharWidth / 2 + 1);
    EncodedRun *tempRuns = new EncodedRun [tempRunsSize];

    // Setup stuff needed to render text with GDI
    SetTextColor(memDC, RGB(255,255,255));
    SetBkColor(memDC, 0);
    RECT rect = { 0, 0, tr->maxCharWidth, tr->charHeight };

    // Run-length encode each ASCII character
    for (int i = 0; i < 256; i++)
	{
        char buf[] = {(char)i};

        // Get the size of this glyph
        SIZE glyphSize;
        GetTextExtentPoint32(memDC, buf, 1, &glyphSize);
//         if (glyphSize.cx > tr->maxCharWidth)
//             tr->maxCharWidth = glyphSize.cx;
//         if (glyphSize.cy > tr->charHeight)
//             tr->charHeight = glyphSize.cy;

        // Ask GDI to draw the character
		ExtTextOut(memDC, 0, 0, ETO_OPAQUE, &rect, buf, 1, 0);

        // Read back what GDI put in the bitmap and construct a run-length encoding
		memset(tempRuns, 0, tempRunsSize);
		EncodedRun *run = tempRuns;
        for (int y = 0; y < tr->charHeight; y++)
		{
            int x = 0;
            while (x < tr->maxCharWidth)
            {
                // Skip blank pixels
                while (!GetPixelFromBuffer(gdiPixels, tr->maxCharWidth, tr->charHeight, x, y))
                {
                    x++;
                    if (x >= tr->maxCharWidth)
                        break;
                }

                // Have we got to the end of the line?
                if (x >= tr->maxCharWidth)
                    continue;

                run->startX = x;
                run->startY = y;
                run->runLen = 0;

                // Count non-blank pixels
                while (GetPixelFromBuffer(gdiPixels, tr->maxCharWidth, tr->charHeight, x, y))
                {
                    x++;
                    run->runLen++;
                    if (x >= tr->maxCharWidth)
                        break;
                }

                run++;
            }
		}

        // Create the glyph to store the encoded runs we've made
		Glyph *glyph = new Glyph(glyphSize.cx);
		tr->glyphs[i] = glyph;

		// Copy the runs into the glyph
		glyph->m_numRuns = run - tempRuns;
		glyph->m_pixelRuns = new EncodedRun [glyph->m_numRuns];
		memcpy(glyph->m_pixelRuns, tempRuns, glyph->m_numRuns * sizeof(EncodedRun));
	}

	delete [] tempRuns;

	// Release the GDI resources
    DeleteDC(winDC);
    DeleteDC(memDC);
	DeleteObject(fontHandle);
	DeleteObject(memBmp);
	DeleteObject(prevBmp);

    return tr;
}

static int DrawTextSimpleClipped(DfFont *tr, DfColour col, DfBitmap *bmp, int _x, int y, char const *text)
{
    int x = _x;
    DfColour *startRow = bmp->pixels + y * (int)bmp->width;
    int width = bmp->width;

    if (y + tr->charHeight < 0 || y > (int)bmp->height)
        return 0;

    while (*text != '\0')
    {
        if (x + tr->maxCharWidth > (int)bmp->width)
            break;

        unsigned char c = *((unsigned char const *)text);
        Glyph *glyph = tr->glyphs[c];
        EncodedRun *rleBuf = glyph->m_pixelRuns;
        for (int i = 0; i < glyph->m_numRuns; i++)
        {
            int y3 = y + rleBuf->startY;
            if (y3 >= 0 && y3 < (int)bmp->height)
            {
                DfColour *thisRow = startRow + rleBuf->startY * width;
                for (unsigned i = 0; i < rleBuf->runLen; i++)
                {
                    int x3 = x + rleBuf->startX + i;
                    if (x3 >= 0 && x3 < width)
                        thisRow[x3] = col;
                }
            }
            rleBuf++;
        }

        x += glyph->m_width;
        text++;
    }

    return _x - x;
}

int DrawTextSimple(DfFont *tr, DfColour col, DfBitmap *bmp, int _x, int y, char const *text)
{
    int x = _x;
    int width = bmp->width;

    if (x < 0 || y < 0 || (y + tr->charHeight) > (int)bmp->height)
        return DrawTextSimpleClipped(tr, col, bmp, _x, y, text);

    DfColour *startRow = bmp->pixels + y * bmp->width;
    while (*text != '\0')
    {
        unsigned char c = *((unsigned char const *)text);
        if (x + tr->glyphs[c]->m_width > (int)bmp->width)
            break;

        // Copy the glyph onto the stack for better cache performance. This increased the
        // performance from 13.8 to 14.4 million chars per second. Madness.
        Glyph glyph = *tr->glyphs[(unsigned char)*text];
        EncodedRun *rleBuf = glyph.m_pixelRuns;
        for (int i = 0; i < glyph.m_numRuns; i++)
        {
            DfColour *startPixel = startRow + rleBuf->startY * width + rleBuf->startX + x;
            for (unsigned i = 0; i < rleBuf->runLen; i++)
                startPixel[i] = col;
            rleBuf++;
        }

        x += glyph.m_width;
        text++;
    }

    return x - _x;
}

int DrawTextLeft(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);
    return DrawTextSimple(tr, c, bmp, x, y, buf);
}

int DrawTextRight(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);

    int width = GetTextWidth(tr, buf);
    return DrawTextSimple(tr, c, bmp, x - width, y, buf);
}

int DrawTextCentre(DfFont *tr, DfColour c, DfBitmap *bmp, int x, int y, char const *text, ...)
{
    char buf[512];
    va_list ap;
    va_start(ap, text);
    vsprintf(buf, text, ap);

    int width = GetTextWidth(tr, buf);
    return DrawTextSimple(tr, c, bmp, x - width/2, y, buf);
}

int GetTextWidth(DfFont *tr, char const *text, int len)
{
	len = IntMin((int)strlen(text), len);
	if (tr->fixedWidth)
	{
		return len * tr->maxCharWidth;
	}
	else
	{
        int width = 0;
        for (int i = 0; i < len; i++)
            width += tr->glyphs[(int)text[i]]->m_width;

		return width;
	}
}
<|endoftext|>


<commit_before><commit_msg>Layout<commit_after><|endoftext|>


<commit_before><commit_msg>Fold only and all empty HTML tags<commit_after><|endoftext|>


<commit_before>//===--- LockFileManager.cpp - File-level Locking Utility------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/LockFileManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>
#include <sys/types.h>
#if LLVM_ON_WIN32
#include <windows.h>
#endif
#if LLVM_ON_UNIX
#include <unistd.h>
#endif
using namespace llvm;

/// \brief Attempt to read the lock file with the given name, if it exists.
///
/// \param LockFileName The name of the lock file to read.
///
/// \returns The process ID of the process that owns this lock file
Optional<std::pair<std::string, int> >
LockFileManager::readLockFile(StringRef LockFileName) {
  // Check whether the lock file exists. If not, clearly there's nothing
  // to read, so we just return.
  if (!sys::fs::exists(LockFileName))
    return None;

  // Read the owning host and PID out of the lock file. If it appears that the
  // owning process is dead, the lock file is invalid.
  std::unique_ptr<MemoryBuffer> MB;
  if (MemoryBuffer::getFile(LockFileName, MB))
    return None;

  StringRef Hostname;
  StringRef PIDStr;
  std::tie(Hostname, PIDStr) = getToken(MB->getBuffer(), " ");
  PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" "));
  int PID;
  if (!PIDStr.getAsInteger(10, PID))
    return std::make_pair(std::string(Hostname), PID);

  // Delete the lock file. It's invalid anyway.
  sys::fs::remove(LockFileName);
  return None;
}

bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
#if LLVM_ON_UNIX && !defined(__ANDROID__)
  char MyHostname[256];
  MyHostname[255] = 0;
  MyHostname[0] = 0;
  gethostname(MyHostname, 255);
  // Check whether the process is dead. If so, we're done.
  if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH)
    return false;
#endif

  return true;
}

LockFileManager::LockFileManager(StringRef FileName)
{
  this->FileName = FileName;
  LockFileName = FileName;
  LockFileName += ".lock";

  // If the lock file already exists, don't bother to try to create our own
  // lock file; it won't work anyway. Just figure out who owns this lock file.
  if ((Owner = readLockFile(LockFileName)))
    return;

  // Create a lock file that is unique to this instance.
  UniqueLockFileName = LockFileName;
  UniqueLockFileName += "-%%%%%%%%";
  int UniqueLockFileID;
  if (error_code EC
        = sys::fs::createUniqueFile(UniqueLockFileName.str(),
                                    UniqueLockFileID,
                                    UniqueLockFileName)) {
    Error = EC;
    return;
  }

  // Write our process ID to our unique lock file.
  {
    raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);

#if LLVM_ON_UNIX
    // FIXME: move getpid() call into LLVM
    char hostname[256];
    hostname[255] = 0;
    hostname[0] = 0;
    gethostname(hostname, 255);
    Out << hostname << ' ' << getpid();
#else
    Out << "localhost 1";
#endif
    Out.close();

    if (Out.has_error()) {
      // We failed to write out PID, so make up an excuse, remove the
      // unique lock file, and fail.
      Error = make_error_code(errc::no_space_on_device);
      sys::fs::remove(UniqueLockFileName.c_str());
      return;
    }
  }

  // Create a hard link from the lock file name. If this succeeds, we're done.
  error_code EC
    = sys::fs::create_hard_link(UniqueLockFileName.str(),
                                      LockFileName.str());
  if (EC == errc::success)
    return;

  // Creating the hard link failed.

#ifdef LLVM_ON_UNIX
  // The creation of the hard link may appear to fail, but if stat'ing the
  // unique file returns a link count of 2, then we can still declare success.
  struct stat StatBuf;
  if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 &&
      StatBuf.st_nlink == 2)
    return;
#endif

  // Someone else managed to create the lock file first. Wipe out our unique
  // lock file (it's useless now) and read the process ID from the lock file.
  sys::fs::remove(UniqueLockFileName.str());
  if ((Owner = readLockFile(LockFileName)))
    return;

  // There is a lock file that nobody owns; try to clean it up and report
  // an error.
  sys::fs::remove(LockFileName.str());
  Error = EC;
}

LockFileManager::LockFileState LockFileManager::getState() const {
  if (Owner)
    return LFS_Shared;

  if (Error)
    return LFS_Error;

  return LFS_Owned;
}

LockFileManager::~LockFileManager() {
  if (getState() != LFS_Owned)
    return;

  // Since we own the lock, remove the lock file and our own unique lock file.
  sys::fs::remove(LockFileName.str());
  sys::fs::remove(UniqueLockFileName.str());
}

void LockFileManager::waitForUnlock() {
  if (getState() != LFS_Shared)
    return;

#if LLVM_ON_WIN32
  unsigned long Interval = 1;
#else
  struct timespec Interval;
  Interval.tv_sec = 0;
  Interval.tv_nsec = 1000000;
#endif
  // Don't wait more than five minutes for the file to appear.
  unsigned MaxSeconds = 300;
  bool LockFileGone = false;
  do {
    // Sleep for the designated interval, to allow the owning process time to
    // finish up and remove the lock file.
    // FIXME: Should we hook in to system APIs to get a notification when the
    // lock file is deleted?
#if LLVM_ON_WIN32
    Sleep(Interval);
#else
    nanosleep(&Interval, NULL);
#endif
    bool LockFileJustDisappeared = false;

    // If the lock file is still expected to be there, check whether it still
    // is.
    if (!LockFileGone) {
      bool Exists;
      if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) {
        LockFileGone = true;
        LockFileJustDisappeared = true;
      }
    }

    // If the lock file is no longer there, check if the original file is
    // available now.
    if (LockFileGone) {
      if (sys::fs::exists(FileName.str())) {
        return;
      }

      // The lock file is gone, so now we're waiting for the original file to
      // show up. If this just happened, reset our waiting intervals and keep
      // waiting.
      if (LockFileJustDisappeared) {
        MaxSeconds = 5;

#if LLVM_ON_WIN32
        Interval = 1;
#else
        Interval.tv_sec = 0;
        Interval.tv_nsec = 1000000;
#endif
        continue;
      }
    }

    // If we're looking for the lock file to disappear, but the process
    // owning the lock died without cleaning up, just bail out.
    if (!LockFileGone &&
        !processStillExecuting((*Owner).first, (*Owner).second)) {
      return;
    }

    // Exponentially increase the time we wait for the lock to be removed.
#if LLVM_ON_WIN32
    Interval *= 2;
#else
    Interval.tv_sec *= 2;
    Interval.tv_nsec *= 2;
    if (Interval.tv_nsec >= 1000000000) {
      ++Interval.tv_sec;
      Interval.tv_nsec -= 1000000000;
    }
#endif
  } while (
#if LLVM_ON_WIN32
           Interval < MaxSeconds * 1000
#else
           Interval.tv_sec < (time_t)MaxSeconds
#endif
           );

  // Give up.
}
<commit_msg>[Support/LockFileManager] Re-apply r203137 and r203138 but use symbolic links only on unix.<commit_after>//===--- LockFileManager.cpp - File-level Locking Utility------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/LockFileManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>
#include <sys/types.h>
#if LLVM_ON_WIN32
#include <windows.h>
#endif
#if LLVM_ON_UNIX
#include <unistd.h>
#endif
using namespace llvm;

/// \brief Attempt to read the lock file with the given name, if it exists.
///
/// \param LockFileName The name of the lock file to read.
///
/// \returns The process ID of the process that owns this lock file
Optional<std::pair<std::string, int> >
LockFileManager::readLockFile(StringRef LockFileName) {
  // Check whether the lock file exists. If not, clearly there's nothing
  // to read, so we just return.
  if (!sys::fs::exists(LockFileName))
    return None;

  // Read the owning host and PID out of the lock file. If it appears that the
  // owning process is dead, the lock file is invalid.
  std::unique_ptr<MemoryBuffer> MB;
  if (MemoryBuffer::getFile(LockFileName, MB))
    return None;

  StringRef Hostname;
  StringRef PIDStr;
  std::tie(Hostname, PIDStr) = getToken(MB->getBuffer(), " ");
  PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" "));
  int PID;
  if (!PIDStr.getAsInteger(10, PID))
    return std::make_pair(std::string(Hostname), PID);

  // Delete the lock file. It's invalid anyway.
  sys::fs::remove(LockFileName);
  return None;
}

bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
#if LLVM_ON_UNIX && !defined(__ANDROID__)
  char MyHostname[256];
  MyHostname[255] = 0;
  MyHostname[0] = 0;
  gethostname(MyHostname, 255);
  // Check whether the process is dead. If so, we're done.
  if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH)
    return false;
#endif

  return true;
}

#if LLVM_ON_UNIX
static error_code unix_create_symbolic_link(const Twine &to,
                                            const Twine &from) {
  // Get arguments.
  SmallString<128> from_storage;
  SmallString<128> to_storage;
  StringRef f = from.toNullTerminatedStringRef(from_storage);
  StringRef t = to.toNullTerminatedStringRef(to_storage);

  if (::symlink(t.begin(), f.begin()) == -1)
    return error_code(errno, system_category());

  return error_code::success();
}
#endif

LockFileManager::LockFileManager(StringRef FileName)
{
  this->FileName = FileName;
  LockFileName = FileName;
  LockFileName += ".lock";

  // If the lock file already exists, don't bother to try to create our own
  // lock file; it won't work anyway. Just figure out who owns this lock file.
  if ((Owner = readLockFile(LockFileName)))
    return;

  // Create a lock file that is unique to this instance.
  UniqueLockFileName = LockFileName;
  UniqueLockFileName += "-%%%%%%%%";
  int UniqueLockFileID;
  if (error_code EC
        = sys::fs::createUniqueFile(UniqueLockFileName.str(),
                                    UniqueLockFileID,
                                    UniqueLockFileName)) {
    Error = EC;
    return;
  }

  // Write our process ID to our unique lock file.
  {
    raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);

#if LLVM_ON_UNIX
    // FIXME: move getpid() call into LLVM
    char hostname[256];
    hostname[255] = 0;
    hostname[0] = 0;
    gethostname(hostname, 255);
    Out << hostname << ' ' << getpid();
#else
    Out << "localhost 1";
#endif
    Out.close();

    if (Out.has_error()) {
      // We failed to write out PID, so make up an excuse, remove the
      // unique lock file, and fail.
      Error = make_error_code(errc::no_space_on_device);
      sys::fs::remove(UniqueLockFileName.c_str());
      return;
    }
  }

  while (1) {
#if LLVM_ON_UNIX
    // Create a symbolic link from the lock file name. If this succeeds, we're
    // done. Note that we are using symbolic link because hard links are not
    // supported by all filesystems.
    error_code EC
      = unix_create_symbolic_link(UniqueLockFileName.str(),
                                        LockFileName.str());
#else
    // We can't use symbolic links for windows.
    // Create a hard link from the lock file name. If this succeeds, we're done.
    error_code EC
      = sys::fs::create_hard_link(UniqueLockFileName.str(),
                                        LockFileName.str());
#endif
    if (EC == errc::success)
      return;

    if (EC != errc::file_exists) {
      Error = EC;
      return;
    }

    // Someone else managed to create the lock file first. Read the process ID
    // from the lock file.
    if ((Owner = readLockFile(LockFileName))) {
      // Wipe out our unique lock file (it's useless now)
      sys::fs::remove(UniqueLockFileName.str());
      return;
    }

    if (!sys::fs::exists(LockFileName.str())) {
      // The previous owner released the lock file before we could read it.
      // Try to get ownership again.
      continue;
    }

    // There is a lock file that nobody owns; try to clean it up and get
    // ownership.
    if ((EC = sys::fs::remove(LockFileName.str()))) {
      Error = EC;
      return;
    }
  }
}

LockFileManager::LockFileState LockFileManager::getState() const {
  if (Owner)
    return LFS_Shared;

  if (Error)
    return LFS_Error;

  return LFS_Owned;
}

LockFileManager::~LockFileManager() {
  if (getState() != LFS_Owned)
    return;

  // Since we own the lock, remove the lock file and our own unique lock file.
  sys::fs::remove(LockFileName.str());
  sys::fs::remove(UniqueLockFileName.str());
}

void LockFileManager::waitForUnlock() {
  if (getState() != LFS_Shared)
    return;

#if LLVM_ON_WIN32
  unsigned long Interval = 1;
#else
  struct timespec Interval;
  Interval.tv_sec = 0;
  Interval.tv_nsec = 1000000;
#endif
  // Don't wait more than five minutes for the file to appear.
  unsigned MaxSeconds = 300;
  bool LockFileGone = false;
  do {
    // Sleep for the designated interval, to allow the owning process time to
    // finish up and remove the lock file.
    // FIXME: Should we hook in to system APIs to get a notification when the
    // lock file is deleted?
#if LLVM_ON_WIN32
    Sleep(Interval);
#else
    nanosleep(&Interval, NULL);
#endif
    bool LockFileJustDisappeared = false;

    // If the lock file is still expected to be there, check whether it still
    // is.
    if (!LockFileGone) {
      bool Exists;
      if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) {
        LockFileGone = true;
        LockFileJustDisappeared = true;
      }
    }

    // If the lock file is no longer there, check if the original file is
    // available now.
    if (LockFileGone) {
      if (sys::fs::exists(FileName.str())) {
        return;
      }

      // The lock file is gone, so now we're waiting for the original file to
      // show up. If this just happened, reset our waiting intervals and keep
      // waiting.
      if (LockFileJustDisappeared) {
        MaxSeconds = 5;

#if LLVM_ON_WIN32
        Interval = 1;
#else
        Interval.tv_sec = 0;
        Interval.tv_nsec = 1000000;
#endif
        continue;
      }
    }

    // If we're looking for the lock file to disappear, but the process
    // owning the lock died without cleaning up, just bail out.
    if (!LockFileGone &&
        !processStillExecuting((*Owner).first, (*Owner).second)) {
      return;
    }

    // Exponentially increase the time we wait for the lock to be removed.
#if LLVM_ON_WIN32
    Interval *= 2;
#else
    Interval.tv_sec *= 2;
    Interval.tv_nsec *= 2;
    if (Interval.tv_nsec >= 1000000000) {
      ++Interval.tv_sec;
      Interval.tv_nsec -= 1000000000;
    }
#endif
  } while (
#if LLVM_ON_WIN32
           Interval < MaxSeconds * 1000
#else
           Interval.tv_sec < (time_t)MaxSeconds
#endif
           );

  // Give up.
}
<|endoftext|>


<commit_before>/*
 * Telefónica Digital - Product Development and Innovation
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Copyright (c) Telefónica Investigación y Desarrollo S.A.U.
 * All rights reserved.
 */

#include "au/log/LogFormatter.h"  // Own interface

#include "au/log/Log.h"

namespace au {
LogFormatter::LogFormatter(const std::string& definition , bool color ) {
  SetFormat(definition,color);
}

void LogFormatter::SetFormat(const std::string& definition , bool color ) {

  definition_ = definition;  // Keep a copy of the definition string
  color_ = color;

  fields_.clear();   // Remove previous definition ( if any )

  if( definition == "none" )
    return; // no format

  // Tokenize with reserved words
  au::token::Tokenizer tokenizer;
  size_t i = 0;
  while (log_reseved_words[i] != NULL) {
    tokenizer.addToken(log_reseved_words[i++]);
  }

  // Parse to get the tokens
  au::token::TokenVector token_vector = tokenizer.parse(definition);

  au::token::Token *token = token_vector.getNextToken();
  while (token) {
    fields_.push_back(token->content);
    token_vector.popToken();
    token = token_vector.getNextToken();
  }
}

  std::string LogFormatter::get(au::SharedPointer<Log> log) const {
    if( color_ )
      return au::str( log->GetColor() ,  "%s" , GetIntern(log).c_str() );
    else
      return GetIntern(log);
  }

std::string LogFormatter::GetIntern(au::SharedPointer<Log> log) const {

  if (definition_ == "all") {
    return log->str();
  }
  std::string output;
  for (size_t i = 0; i < fields_.size(); i++) {
    output.append(log->Get(fields_[i]));
  }
  return output;
}
}<commit_msg>Fix bug in log generation<commit_after>/*
 * Telefónica Digital - Product Development and Innovation
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Copyright (c) Telefónica Investigación y Desarrollo S.A.U.
 * All rights reserved.
 */

#include "au/log/LogFormatter.h"  // Own interface

#include "au/log/Log.h"

namespace au {
LogFormatter::LogFormatter(const std::string& definition , bool color ) {
  SetFormat(definition,color);
}

void LogFormatter::SetFormat(const std::string& definition , bool color ) {

  definition_ = definition;  // Keep a copy of the definition string
  color_ = color;

  fields_.clear();   // Remove previous definition ( if any )

  if( definition == "none" )
    return; // no format

  // Tokenize with reserved words
  au::token::Tokenizer tokenizer;
  size_t i = 0;
  while (log_reseved_words[i] != NULL) {
    tokenizer.addToken(log_reseved_words[i++]);
  }

  // Parse to get the tokens
  au::token::TokenVector token_vector = tokenizer.parse(definition);

  au::token::Token *token = token_vector.getNextToken();
  while (token) {
    fields_.push_back(token->content);
    token_vector.popToken();
    token = token_vector.getNextToken();
  }
}

  std::string LogFormatter::get(au::SharedPointer<Log> log) const {
    if( color_ )
      return au::str( log->GetColor() ,  "%s" , GetIntern(log).c_str() );
    else
      return GetIntern(log);
  }

std::string LogFormatter::GetIntern(au::SharedPointer<Log> log) const {

  if (definition_ == "all") {
    return log->str();
  }
  std::ostringstream output;
  for (size_t i = 0; i < fields_.size(); i++) {
    output << log->Get(fields_[i]);
  }
  return output.str();
}
}<|endoftext|>


<commit_before>//===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//

#include "ARMSubtarget.h"
#include "ARMFrameLowering.h"
#include "ARMISelLowering.h"
#include "ARMInstrInfo.h"
#include "ARMSelectionDAGInfo.h"
#include "ARMSubtarget.h"
#include "ARMMachineFunctionInfo.h"
#include "Thumb1FrameLowering.h"
#include "Thumb1InstrInfo.h"
#include "Thumb2InstrInfo.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;

#define DEBUG_TYPE "arm-subtarget"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "ARMGenSubtargetInfo.inc"

static cl::opt<bool>
ReserveR9("arm-reserve-r9", cl::Hidden,
          cl::desc("Reserve R9, making it unavailable as GPR"));

static cl::opt<bool>
ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden);

static cl::opt<bool>
UseFusedMulOps("arm-use-mulops",
               cl::init(true), cl::Hidden);

namespace {
enum AlignMode {
  DefaultAlign,
  StrictAlign,
  NoStrictAlign
};
}

static cl::opt<AlignMode>
Align(cl::desc("Load/store alignment support"),
      cl::Hidden, cl::init(DefaultAlign),
      cl::values(
          clEnumValN(DefaultAlign,  "arm-default-align",
                     "Generate unaligned accesses only on hardware/OS "
                     "combinations that are known to support them"),
          clEnumValN(StrictAlign,   "arm-strict-align",
                     "Disallow all unaligned memory accesses"),
          clEnumValN(NoStrictAlign, "arm-no-strict-align",
                     "Allow unaligned memory accesses"),
          clEnumValEnd));

enum ITMode {
  DefaultIT,
  RestrictedIT,
  NoRestrictedIT
};

static cl::opt<ITMode>
IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
   cl::ZeroOrMore,
   cl::values(clEnumValN(DefaultIT, "arm-default-it",
                         "Generate IT block based on arch"),
              clEnumValN(RestrictedIT, "arm-restrict-it",
                         "Disallow deprecated IT based on ARMv8"),
              clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
                         "Allow IT blocks based on ARMv7"),
              clEnumValEnd));

static std::string computeDataLayout(ARMSubtarget &ST) {
  std::string Ret = "";

  if (ST.isLittle())
    // Little endian.
    Ret += "e";
  else
    // Big endian.
    Ret += "E";

  Ret += DataLayout::getManglingComponent(ST.getTargetTriple());

  // Pointers are 32 bits and aligned to 32 bits.
  Ret += "-p:32:32";

  // ABIs other than APCS have 64 bit integers with natural alignment.
  if (!ST.isAPCS_ABI())
    Ret += "-i64:64";

  // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
  // bits, others to 64 bits. We always try to align to 64 bits.
  if (ST.isAPCS_ABI())
    Ret += "-f64:32:64";

  // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
  // to 64. We always ty to give them natural alignment.
  if (ST.isAPCS_ABI())
    Ret += "-v64:32:64-v128:32:128";
  else
    Ret += "-v128:64:128";

  // Try to align aggregates to 32 bits (the default is 64 bits, which has no
  // particular hardware support on 32-bit ARM).
  Ret += "-a:0:32";

  // Integer registers are 32 bits.
  Ret += "-n32";

  // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
  // aligned everywhere else.
  if (ST.isTargetNaCl())
    Ret += "-S128";
  else if (ST.isAAPCS_ABI())
    Ret += "-S64";
  else
    Ret += "-S32";

  return Ret;
}

/// initializeSubtargetDependencies - Initializes using a CPU and feature string
/// so that we can use initializer lists for subtarget initialization.
ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
                                                            StringRef FS) {
  initializeEnvironment();
  initSubtargetFeatures(CPU, FS);
  return *this;
}

ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
                           const std::string &FS, const TargetMachine &TM,
                           bool IsLittle)
    : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others),
      ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle),
      TargetTriple(TT), Options(TM.Options), TargetABI(ARM_ABI_UNKNOWN),
      DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS))),
      TSInfo(DL),
      InstrInfo(isThumb1Only()
                    ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
                    : !isThumb()
                          ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
                          : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
      TLInfo(TM),
      FrameLowering(!isThumb1Only()
                        ? new ARMFrameLowering(*this)
                        : (ARMFrameLowering *)new Thumb1FrameLowering(*this)) {}

void ARMSubtarget::initializeEnvironment() {
  HasV4TOps = false;
  HasV5TOps = false;
  HasV5TEOps = false;
  HasV6Ops = false;
  HasV6MOps = false;
  HasV6T2Ops = false;
  HasV7Ops = false;
  HasV8Ops = false;
  HasVFPv2 = false;
  HasVFPv3 = false;
  HasVFPv4 = false;
  HasFPARMv8 = false;
  HasNEON = false;
  UseNEONForSinglePrecisionFP = false;
  UseMulOps = UseFusedMulOps;
  SlowFPVMLx = false;
  HasVMLxForwarding = false;
  SlowFPBrcc = false;
  InThumbMode = false;
  HasThumb2 = false;
  NoARM = false;
  IsR9Reserved = ReserveR9;
  UseMovt = false;
  SupportsTailCall = false;
  HasFP16 = false;
  HasD16 = false;
  HasHardwareDivide = false;
  HasHardwareDivideInARM = false;
  HasT2ExtractPack = false;
  HasDataBarrier = false;
  Pref32BitThumb = false;
  AvoidCPSRPartialUpdate = false;
  AvoidMOVsShifterOperand = false;
  HasRAS = false;
  HasMPExtension = false;
  HasVirtualization = false;
  FPOnlySP = false;
  HasPerfMon = false;
  HasTrustZone = false;
  HasCrypto = false;
  HasCRC = false;
  HasZeroCycleZeroing = false;
  AllowsUnalignedMem = false;
  Thumb2DSP = false;
  UseNaClTrap = false;
  UnsafeFPMath = false;
}

void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
  if (CPUString.empty()) {
    if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s"))
      // Default to the Swift CPU when targeting armv7s/thumbv7s.
      CPUString = "swift";
    else
      CPUString = "generic";
  }

  // Insert the architecture feature derived from the target triple into the
  // feature string. This is important for setting features that are implied
  // based on the architecture version.
  std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(),
                                              CPUString);
  if (!FS.empty()) {
    if (!ArchFS.empty())
      ArchFS = ArchFS + "," + FS.str();
    else
      ArchFS = FS;
  }
  ParseSubtargetFeatures(CPUString, ArchFS);

  // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
  // Assert this for now to make the change obvious.
  assert(hasV6T2Ops() || !hasThumb2());

  // Keep a pointer to static instruction cost data for the specified CPU.
  SchedModel = getSchedModelForCPU(CPUString);

  // Initialize scheduling itinerary for the specified CPU.
  InstrItins = getInstrItineraryForCPU(CPUString);

  if (TargetABI == ARM_ABI_UNKNOWN) {
    switch (TargetTriple.getEnvironment()) {
    case Triple::Android:
    case Triple::EABI:
    case Triple::EABIHF:
    case Triple::GNUEABI:
    case Triple::GNUEABIHF:
      TargetABI = ARM_ABI_AAPCS;
      break;
    default:
      if ((isTargetIOS() && isMClass()) ||
          (TargetTriple.isOSBinFormatMachO() &&
           TargetTriple.getOS() == Triple::UnknownOS))
        TargetABI = ARM_ABI_AAPCS;
      else
        TargetABI = ARM_ABI_APCS;
      break;
    }
  }

  // FIXME: this is invalid for WindowsCE
  if (isTargetWindows()) {
    TargetABI = ARM_ABI_AAPCS;
    NoARM = true;
  }

  if (isAAPCS_ABI())
    stackAlignment = 8;
  if (isTargetNaCl())
    stackAlignment = 16;

  UseMovt = hasV6T2Ops() && ArmUseMOVT;

  if (isTargetMachO()) {
    IsR9Reserved = ReserveR9 || !HasV6Ops;
    SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0);
  } else {
    IsR9Reserved = ReserveR9;
    SupportsTailCall = !isThumb1Only();
  }

  if (Align == DefaultAlign) {
    // Assume pre-ARMv6 doesn't support unaligned accesses.
    //
    // ARMv6 may or may not support unaligned accesses depending on the
    // SCTLR.U bit, which is architecture-specific. We assume ARMv6
    // Darwin and NetBSD targets support unaligned accesses, and others don't.
    //
    // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
    // which raises an alignment fault on unaligned accesses. Linux
    // defaults this bit to 0 and handles it as a system-wide (not
    // per-process) setting. It is therefore safe to assume that ARMv7+
    // Linux targets support unaligned accesses. The same goes for NaCl.
    //
    // The above behavior is consistent with GCC.
    AllowsUnalignedMem =
      (hasV7Ops() && (isTargetLinux() || isTargetNaCl() ||
                      isTargetNetBSD())) ||
      (hasV6Ops() && (isTargetMachO() || isTargetNetBSD()));
  } else {
    AllowsUnalignedMem = !(Align == StrictAlign);
  }

  // No v6M core supports unaligned memory access (v6M ARM ARM A3.2)
  if (isV6M())
    AllowsUnalignedMem = false;

  switch (IT) {
  case DefaultIT:
    RestrictIT = hasV8Ops() ? true : false;
    break;
  case RestrictedIT:
    RestrictIT = true;
    break;
  case NoRestrictedIT:
    RestrictIT = false;
    break;
  }

  // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
  uint64_t Bits = getFeatureBits();
  if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters
      (Options.UnsafeFPMath || isTargetDarwin()))
    UseNEONForSinglePrecisionFP = true;
}

/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
bool
ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
                                 Reloc::Model RelocM) const {
  if (RelocM == Reloc::Static)
    return false;

  // Materializable GVs (in JIT lazy compilation mode) do not require an extra
  // load from stub.
  bool isDecl = GV->hasAvailableExternallyLinkage();
  if (GV->isDeclaration() && !GV->isMaterializable())
    isDecl = true;

  if (!isTargetMachO()) {
    // Extra load is needed for all externally visible.
    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
      return false;
    return true;
  } else {
    if (RelocM == Reloc::PIC_) {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;

      // If symbol visibility is hidden, we have a stub for common symbol
      // references and external declarations.
      if (isDecl || GV->hasCommonLinkage())
        // Hidden $non_lazy_ptr reference.
        return true;

      return false;
    } else {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;
    }
  }

  return false;
}

unsigned ARMSubtarget::getMispredictionPenalty() const {
  return SchedModel.MispredictPenalty;
}

bool ARMSubtarget::hasSinCos() const {
  return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0);
}

// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
bool ARMSubtarget::enablePostMachineScheduler() const {
  return (!isThumb() || hasThumb2());
}

bool ARMSubtarget::enableAtomicExpand() const {
  return hasAnyDataBarrier() && !isThumb1Only();
}

bool ARMSubtarget::useMovt(const MachineFunction &MF) const {
  // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
  // immediates as it is inherently position independent, and may be out of
  // range otherwise.
  return UseMovt && (isTargetWindows() ||
                     !MF.getFunction()->getAttributes().hasAttribute(
                         AttributeSet::FunctionIndex, Attribute::MinSize));
}
<commit_msg>ARM: drop check for triple that's no longer used.<commit_after>//===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//

#include "ARMSubtarget.h"
#include "ARMFrameLowering.h"
#include "ARMISelLowering.h"
#include "ARMInstrInfo.h"
#include "ARMSelectionDAGInfo.h"
#include "ARMSubtarget.h"
#include "ARMMachineFunctionInfo.h"
#include "Thumb1FrameLowering.h"
#include "Thumb1InstrInfo.h"
#include "Thumb2InstrInfo.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;

#define DEBUG_TYPE "arm-subtarget"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "ARMGenSubtargetInfo.inc"

static cl::opt<bool>
ReserveR9("arm-reserve-r9", cl::Hidden,
          cl::desc("Reserve R9, making it unavailable as GPR"));

static cl::opt<bool>
ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden);

static cl::opt<bool>
UseFusedMulOps("arm-use-mulops",
               cl::init(true), cl::Hidden);

namespace {
enum AlignMode {
  DefaultAlign,
  StrictAlign,
  NoStrictAlign
};
}

static cl::opt<AlignMode>
Align(cl::desc("Load/store alignment support"),
      cl::Hidden, cl::init(DefaultAlign),
      cl::values(
          clEnumValN(DefaultAlign,  "arm-default-align",
                     "Generate unaligned accesses only on hardware/OS "
                     "combinations that are known to support them"),
          clEnumValN(StrictAlign,   "arm-strict-align",
                     "Disallow all unaligned memory accesses"),
          clEnumValN(NoStrictAlign, "arm-no-strict-align",
                     "Allow unaligned memory accesses"),
          clEnumValEnd));

enum ITMode {
  DefaultIT,
  RestrictedIT,
  NoRestrictedIT
};

static cl::opt<ITMode>
IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
   cl::ZeroOrMore,
   cl::values(clEnumValN(DefaultIT, "arm-default-it",
                         "Generate IT block based on arch"),
              clEnumValN(RestrictedIT, "arm-restrict-it",
                         "Disallow deprecated IT based on ARMv8"),
              clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
                         "Allow IT blocks based on ARMv7"),
              clEnumValEnd));

static std::string computeDataLayout(ARMSubtarget &ST) {
  std::string Ret = "";

  if (ST.isLittle())
    // Little endian.
    Ret += "e";
  else
    // Big endian.
    Ret += "E";

  Ret += DataLayout::getManglingComponent(ST.getTargetTriple());

  // Pointers are 32 bits and aligned to 32 bits.
  Ret += "-p:32:32";

  // ABIs other than APCS have 64 bit integers with natural alignment.
  if (!ST.isAPCS_ABI())
    Ret += "-i64:64";

  // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
  // bits, others to 64 bits. We always try to align to 64 bits.
  if (ST.isAPCS_ABI())
    Ret += "-f64:32:64";

  // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
  // to 64. We always ty to give them natural alignment.
  if (ST.isAPCS_ABI())
    Ret += "-v64:32:64-v128:32:128";
  else
    Ret += "-v128:64:128";

  // Try to align aggregates to 32 bits (the default is 64 bits, which has no
  // particular hardware support on 32-bit ARM).
  Ret += "-a:0:32";

  // Integer registers are 32 bits.
  Ret += "-n32";

  // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
  // aligned everywhere else.
  if (ST.isTargetNaCl())
    Ret += "-S128";
  else if (ST.isAAPCS_ABI())
    Ret += "-S64";
  else
    Ret += "-S32";

  return Ret;
}

/// initializeSubtargetDependencies - Initializes using a CPU and feature string
/// so that we can use initializer lists for subtarget initialization.
ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
                                                            StringRef FS) {
  initializeEnvironment();
  initSubtargetFeatures(CPU, FS);
  return *this;
}

ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
                           const std::string &FS, const TargetMachine &TM,
                           bool IsLittle)
    : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others),
      ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle),
      TargetTriple(TT), Options(TM.Options), TargetABI(ARM_ABI_UNKNOWN),
      DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS))),
      TSInfo(DL),
      InstrInfo(isThumb1Only()
                    ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
                    : !isThumb()
                          ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
                          : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
      TLInfo(TM),
      FrameLowering(!isThumb1Only()
                        ? new ARMFrameLowering(*this)
                        : (ARMFrameLowering *)new Thumb1FrameLowering(*this)) {}

void ARMSubtarget::initializeEnvironment() {
  HasV4TOps = false;
  HasV5TOps = false;
  HasV5TEOps = false;
  HasV6Ops = false;
  HasV6MOps = false;
  HasV6T2Ops = false;
  HasV7Ops = false;
  HasV8Ops = false;
  HasVFPv2 = false;
  HasVFPv3 = false;
  HasVFPv4 = false;
  HasFPARMv8 = false;
  HasNEON = false;
  UseNEONForSinglePrecisionFP = false;
  UseMulOps = UseFusedMulOps;
  SlowFPVMLx = false;
  HasVMLxForwarding = false;
  SlowFPBrcc = false;
  InThumbMode = false;
  HasThumb2 = false;
  NoARM = false;
  IsR9Reserved = ReserveR9;
  UseMovt = false;
  SupportsTailCall = false;
  HasFP16 = false;
  HasD16 = false;
  HasHardwareDivide = false;
  HasHardwareDivideInARM = false;
  HasT2ExtractPack = false;
  HasDataBarrier = false;
  Pref32BitThumb = false;
  AvoidCPSRPartialUpdate = false;
  AvoidMOVsShifterOperand = false;
  HasRAS = false;
  HasMPExtension = false;
  HasVirtualization = false;
  FPOnlySP = false;
  HasPerfMon = false;
  HasTrustZone = false;
  HasCrypto = false;
  HasCRC = false;
  HasZeroCycleZeroing = false;
  AllowsUnalignedMem = false;
  Thumb2DSP = false;
  UseNaClTrap = false;
  UnsafeFPMath = false;
}

void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
  if (CPUString.empty()) {
    if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s"))
      // Default to the Swift CPU when targeting armv7s/thumbv7s.
      CPUString = "swift";
    else
      CPUString = "generic";
  }

  // Insert the architecture feature derived from the target triple into the
  // feature string. This is important for setting features that are implied
  // based on the architecture version.
  std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(),
                                              CPUString);
  if (!FS.empty()) {
    if (!ArchFS.empty())
      ArchFS = ArchFS + "," + FS.str();
    else
      ArchFS = FS;
  }
  ParseSubtargetFeatures(CPUString, ArchFS);

  // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
  // Assert this for now to make the change obvious.
  assert(hasV6T2Ops() || !hasThumb2());

  // Keep a pointer to static instruction cost data for the specified CPU.
  SchedModel = getSchedModelForCPU(CPUString);

  // Initialize scheduling itinerary for the specified CPU.
  InstrItins = getInstrItineraryForCPU(CPUString);

  if (TargetABI == ARM_ABI_UNKNOWN) {
    switch (TargetTriple.getEnvironment()) {
    case Triple::Android:
    case Triple::EABI:
    case Triple::EABIHF:
    case Triple::GNUEABI:
    case Triple::GNUEABIHF:
      TargetABI = ARM_ABI_AAPCS;
      break;
    default:
      if (TargetTriple.isOSBinFormatMachO() &&
          TargetTriple.getOS() == Triple::UnknownOS)
        TargetABI = ARM_ABI_AAPCS;
      else
        TargetABI = ARM_ABI_APCS;
      break;
    }
  }

  // FIXME: this is invalid for WindowsCE
  if (isTargetWindows()) {
    TargetABI = ARM_ABI_AAPCS;
    NoARM = true;
  }

  if (isAAPCS_ABI())
    stackAlignment = 8;
  if (isTargetNaCl())
    stackAlignment = 16;

  UseMovt = hasV6T2Ops() && ArmUseMOVT;

  if (isTargetMachO()) {
    IsR9Reserved = ReserveR9 || !HasV6Ops;
    SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0);
  } else {
    IsR9Reserved = ReserveR9;
    SupportsTailCall = !isThumb1Only();
  }

  if (Align == DefaultAlign) {
    // Assume pre-ARMv6 doesn't support unaligned accesses.
    //
    // ARMv6 may or may not support unaligned accesses depending on the
    // SCTLR.U bit, which is architecture-specific. We assume ARMv6
    // Darwin and NetBSD targets support unaligned accesses, and others don't.
    //
    // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
    // which raises an alignment fault on unaligned accesses. Linux
    // defaults this bit to 0 and handles it as a system-wide (not
    // per-process) setting. It is therefore safe to assume that ARMv7+
    // Linux targets support unaligned accesses. The same goes for NaCl.
    //
    // The above behavior is consistent with GCC.
    AllowsUnalignedMem =
      (hasV7Ops() && (isTargetLinux() || isTargetNaCl() ||
                      isTargetNetBSD())) ||
      (hasV6Ops() && (isTargetMachO() || isTargetNetBSD()));
  } else {
    AllowsUnalignedMem = !(Align == StrictAlign);
  }

  // No v6M core supports unaligned memory access (v6M ARM ARM A3.2)
  if (isV6M())
    AllowsUnalignedMem = false;

  switch (IT) {
  case DefaultIT:
    RestrictIT = hasV8Ops() ? true : false;
    break;
  case RestrictedIT:
    RestrictIT = true;
    break;
  case NoRestrictedIT:
    RestrictIT = false;
    break;
  }

  // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
  uint64_t Bits = getFeatureBits();
  if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters
      (Options.UnsafeFPMath || isTargetDarwin()))
    UseNEONForSinglePrecisionFP = true;
}

/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
bool
ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
                                 Reloc::Model RelocM) const {
  if (RelocM == Reloc::Static)
    return false;

  // Materializable GVs (in JIT lazy compilation mode) do not require an extra
  // load from stub.
  bool isDecl = GV->hasAvailableExternallyLinkage();
  if (GV->isDeclaration() && !GV->isMaterializable())
    isDecl = true;

  if (!isTargetMachO()) {
    // Extra load is needed for all externally visible.
    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
      return false;
    return true;
  } else {
    if (RelocM == Reloc::PIC_) {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;

      // If symbol visibility is hidden, we have a stub for common symbol
      // references and external declarations.
      if (isDecl || GV->hasCommonLinkage())
        // Hidden $non_lazy_ptr reference.
        return true;

      return false;
    } else {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;
    }
  }

  return false;
}

unsigned ARMSubtarget::getMispredictionPenalty() const {
  return SchedModel.MispredictPenalty;
}

bool ARMSubtarget::hasSinCos() const {
  return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0);
}

// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
bool ARMSubtarget::enablePostMachineScheduler() const {
  return (!isThumb() || hasThumb2());
}

bool ARMSubtarget::enableAtomicExpand() const {
  return hasAnyDataBarrier() && !isThumb1Only();
}

bool ARMSubtarget::useMovt(const MachineFunction &MF) const {
  // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
  // immediates as it is inherently position independent, and may be out of
  // range otherwise.
  return UseMovt && (isTargetWindows() ||
                     !MF.getFunction()->getAttributes().hasAttribute(
                         AttributeSet::FunctionIndex, Attribute::MinSize));
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <csignal>
#include <fstream>

#include <pthread.h>
#include <boost/program_options.hpp>
#include "nodeinfo_types.h"
#include "base/connection_info.h"
#include <base/logging.h>
#include <base/misc_utils.h>
#include <base/contrail_ports.h>
#include <base/task.h>
#include <io/process_signal.h>
#include <config_client_manager.h>
#include <db/db_graph.h>
#include <ifmap/client/config_json_parser.h>
#include <ifmap/ifmap_link_table.h>
#include "ifmap/ifmap_sandesh_context.h"
#include <ifmap/ifmap_server.h>
#include <ifmap/ifmap_xmpp.h>
#include <io/event_manager.h>
#include <vnc_cfg_types.h>
#include <cmn/dns.h>
#include <bind/bind_util.h>
#include <mgr/dns_mgr.h>
#include <mgr/dns_oper.h>
#include <bind/named_config.h>
#include <cfg/dns_config.h>
#include <cfg/dns_config_parser.h>
#include <agent/agent_xmpp_init.h>
#include "cmn/dns_options.h"
#include <sandesh/common/vns_types.h>
#include <sandesh/common/vns_constants.h>
#include <uve/uve.h>
#include "xmpp/xmpp_sandesh.h"

namespace opt = boost::program_options;
using namespace boost::asio::ip;
using namespace std;
using process::ConnectionInfo;
using process::ConnectionStateManager;
using process::GetProcessStateCb;
using process::ProcessState;
using process::ConnectionType;
using process::ConnectionTypeName;
using process::g_process_info_constants;
using process::Signal;

uint64_t start_time;
TaskTrigger *dns_info_trigger;
Timer *dns_info_log_timer;
static Options options;

bool DnsInfoLogTimer() {
    dns_info_trigger->Set();
    return false;
}

bool DnsInfoLogger() {
    DnsUveClient::SendDnsUve(start_time);

    dns_info_log_timer->Cancel();
    dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer),NULL);
    return true;
}

static void DnsServerGetProcessStateCb(
   const ConfigClientManager *config_client_manager,
   const std::vector<ConnectionInfo> &cinfos,
   ProcessState::type &state, std::string &message,
   std::vector<ConnectionTypeName> expected_connections) {
    GetProcessStateCb(cinfos, state, message, expected_connections);
    if (state == ProcessState::NON_FUNCTIONAL)
        return;
    if (!config_client_manager->GetEndOfRibComputed()) {
        state = ProcessState::NON_FUNCTIONAL;
        message = "IFMap Server End-Of-RIB not computed";
    }
}

static string FileRead(const string &filename) {
    ifstream file(filename.c_str());
    string content((istreambuf_iterator<char>(file)),
                   istreambuf_iterator<char>());
    return content;
}

static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser) {
    IFMapLinkTable_Init(server->database(), server->graph());
    vnc_cfg_JsonParserInit(json_parser);
    vnc_cfg_Server_ModuleInit(server->database(), server->graph());
    server->Initialize();
}

static bool OptionsParse(Options &options, int argc, char *argv[]) {
    try {
        options.Parse(*Dns::GetEventManager(), argc, argv);
        return true;
    } catch (boost::program_options::error &e) {
        cout << "Error " << e.what() << endl;
    } catch (...) {
        cout << "Options Parser: Caught fatal unknown exception" << endl;
    }

    return false;
}

void ReConfigSignalHandler(const boost::system::error_code &error, int sig) {
    if (error) {
        LOG(ERROR, "SIGHUP handler ERROR: " << error);
        return;
    }
    options.ParseReConfig();
}

int main(int argc, char *argv[]) {
    // Initialize the task scheduler
    int num_threads_to_tbb = TaskScheduler::GetDefaultThreadCount() +
        ConfigClientManager::GetNumWorkers();
    TaskScheduler::Initialize(num_threads_to_tbb);

    // Create DB table and event manager
    Dns::Init();

    // Process options from command-line and configuration file.
    if (!OptionsParse(options, argc, argv)) {
        exit(-1);
    }

    srand(unsigned(time(NULL)));
    std::vector<Signal::SignalHandler> sighup_handlers = boost::assign::list_of
        (boost::bind(&ReConfigSignalHandler, _1, _2));
    Signal::SignalCallbackMap smap = boost::assign::map_list_of
        (SIGHUP, sighup_handlers);
    Signal signal(Dns::GetEventManager(), smap);

    Dns::SetProgramName(argv[0]);
    Module::type module = Module::DNS;
    string module_name = g_vns_constants.ModuleNames.find(module)->second;

    std::string log_property_file = options.log_property_file();
    if (log_property_file.size()) {
        LoggingInit(log_property_file);
    }
    else {
        LoggingInit(options.log_file(), options.log_file_size(),
                    options.log_files_count(), options.use_syslog(),
                    options.syslog_facility(), module_name,
                    SandeshLevelTolog4Level(
                        Sandesh::StringToLevel(options.log_level())));
    }

    string build_info_str;
    Dns::GetVersion(build_info_str);
    MiscUtils::LogVersionInfo(build_info_str, Category::DNSAGENT);

    if (options.collectors_configured()) {
        Dns::SetCollector(options.collector_server_list()[0]);
    }
    Dns::SetHttpPort(options.http_server_port());
    Dns::SetDnsPort(options.dns_server_port());

    boost::system::error_code ec;
    string hostname = host_name(ec);
    Dns::SetHostName(hostname);

    ConnectionStateManager::GetInstance();
    NodeType::type node_type =
        g_vns_constants.Module2NodeType.find(module)->second;
    bool success(Sandesh::InitGenerator(
                 module_name,
                 options.hostname(),
                 g_vns_constants.NodeTypeNames.find(node_type)->second,
                 g_vns_constants.INSTANCE_ID_DEFAULT,
                 Dns::GetEventManager(),
                 options.http_server_port(),
                 options.randomized_collector_server_list(),
                 NULL,
                 Sandesh::DerivedStats(),
                 options.sandesh_config()));
    if (!success) {
        LOG(ERROR, "SANDESH: Initialization FAILED ... exiting");
        Sandesh::Uninit();
        exit(1);
    }
    Sandesh::SetLoggingParams(options.log_local(), options.log_category(),
                              options.log_level());

    // XXX Disable logging -- for test purposes only
    if (options.log_disable()) {
        SetLoggingDisabled(true);
    }

    // DNS::SetTestMode(options.test_mode());

    DB config_db(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"));
    DBGraph config_graph;
    IFMapServer ifmap_server(&config_db, &config_graph,
                             Dns::GetEventManager()->io_service());

    ConfigFactory::Register<ConfigJsonParserBase>(
                          boost::factory<ConfigJsonParser *>());
    ConfigClientManager *config_client_manager =
        new ConfigClientManager(Dns::GetEventManager(), options.hostname(),
                  module_name, options.configdb_options());
    ConfigJsonParser *json_parser =
      static_cast<ConfigJsonParser *>(config_client_manager->config_json_parser());
    json_parser->ifmap_server_set(&ifmap_server);
    IFMap_Initialize(&ifmap_server, json_parser);

    DnsManager dns_manager;
    Dns::SetDnsManager(&dns_manager);
    dns_manager.Initialize(&config_db, &config_graph,
                           options.named_config_dir(),
                           options.named_config_file(),
                           options.named_log_file(),
                           options.rndc_config_file(),
                           options.rndc_secret(),
                           options.named_max_cache_size(),
                           options.named_max_retransmissions(),
                           options.named_retransmission_interval());
    DnsConfigParser parser(&config_db);
    parser.Parse(FileRead(options.config_file()));

    Dns::SetSelfIp(options.host_ip());
    if (!DnsAgentXmppManager::Init(options.xmpp_auth_enabled(),
                                   options.xmpp_server_cert(),
                                   options.xmpp_server_key(),
                                   options.xmpp_ca_cert())) {
        LOG(ERROR, "Address already in use " << ContrailPorts::DnsXmpp());
        exit(1);
    }

    XmppSandeshContext xmpp_sandesh_context;
    xmpp_sandesh_context.xmpp_server = Dns::GetXmppServer();
    Sandesh::set_module_context("XMPP", &xmpp_sandesh_context);
    IFMapSandeshContext ifmap_sandesh_context(&ifmap_server);
    Sandesh::set_module_context("IFMap", &ifmap_sandesh_context);

    start_time = UTCTimestampUsec();
    dns_info_trigger =
            new TaskTrigger(boost::bind(&DnsInfoLogger),
                    TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0);

    dns_info_log_timer =
        TimerManager::CreateTimer(*(Dns::GetEventManager()->io_service()),
                                                   "Dns Info log timer");
    dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer), NULL);
    Dns::SetSelfIp(options.host_ip());
    ifmap_server.set_config_manager(config_client_manager);

    //
    // Determine if the number of connections is as expected.
    // 1. Cassandra Server
    // 2. AMQP Server
    //
    std::vector<ConnectionTypeName> expected_connections;
    expected_connections = boost::assign::list_of
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::COLLECTOR)->second, ""))
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::DATABASE)->second, "Cassandra"))
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::DATABASE)->second, "RabbitMQ"));

    ConnectionStateManager::GetInstance()->Init(
        *(Dns::GetEventManager()->io_service()), options.hostname(),
        module_name, g_vns_constants.INSTANCE_ID_DEFAULT,
        boost::bind(&DnsServerGetProcessStateCb, config_client_manager, _1, _2, _3,
                    expected_connections), "ObjectDns");

    dns_manager.set_config_manager(config_client_manager);
    options.set_config_client_manager(config_client_manager);
    config_client_manager->Initialize();

    Dns::GetEventManager()->Run();
    signal.Terminate();
    return 0;
}
<commit_msg>control-dns must use correct fqdn<commit_after>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <csignal>
#include <fstream>

#include <pthread.h>
#include <boost/program_options.hpp>
#include "nodeinfo_types.h"
#include "base/connection_info.h"
#include <base/logging.h>
#include <base/misc_utils.h>
#include <base/contrail_ports.h>
#include <base/task.h>
#include <io/process_signal.h>
#include <config_client_manager.h>
#include <db/db_graph.h>
#include <ifmap/client/config_json_parser.h>
#include <ifmap/ifmap_link_table.h>
#include "ifmap/ifmap_sandesh_context.h"
#include <ifmap/ifmap_server.h>
#include <ifmap/ifmap_xmpp.h>
#include <io/event_manager.h>
#include <vnc_cfg_types.h>
#include <cmn/dns.h>
#include <bind/bind_util.h>
#include <mgr/dns_mgr.h>
#include <mgr/dns_oper.h>
#include <bind/named_config.h>
#include <cfg/dns_config.h>
#include <cfg/dns_config_parser.h>
#include <agent/agent_xmpp_init.h>
#include "cmn/dns_options.h"
#include <sandesh/common/vns_types.h>
#include <sandesh/common/vns_constants.h>
#include <uve/uve.h>
#include "xmpp/xmpp_sandesh.h"

namespace opt = boost::program_options;
using namespace boost::asio::ip;
using namespace std;
using process::ConnectionInfo;
using process::ConnectionStateManager;
using process::GetProcessStateCb;
using process::ProcessState;
using process::ConnectionType;
using process::ConnectionTypeName;
using process::g_process_info_constants;
using process::Signal;

uint64_t start_time;
TaskTrigger *dns_info_trigger;
Timer *dns_info_log_timer;
static Options options;

bool DnsInfoLogTimer() {
    dns_info_trigger->Set();
    return false;
}

bool DnsInfoLogger() {
    DnsUveClient::SendDnsUve(start_time);

    dns_info_log_timer->Cancel();
    dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer),NULL);
    return true;
}

static void DnsServerGetProcessStateCb(
   const ConfigClientManager *config_client_manager,
   const std::vector<ConnectionInfo> &cinfos,
   ProcessState::type &state, std::string &message,
   std::vector<ConnectionTypeName> expected_connections) {
    GetProcessStateCb(cinfos, state, message, expected_connections);
    if (state == ProcessState::NON_FUNCTIONAL)
        return;
    if (!config_client_manager->GetEndOfRibComputed()) {
        state = ProcessState::NON_FUNCTIONAL;
        message = "IFMap Server End-Of-RIB not computed";
    }
}

static string FileRead(const string &filename) {
    ifstream file(filename.c_str());
    string content((istreambuf_iterator<char>(file)),
                   istreambuf_iterator<char>());
    return content;
}

static void IFMap_Initialize(IFMapServer *server, ConfigJsonParser *json_parser) {
    IFMapLinkTable_Init(server->database(), server->graph());
    vnc_cfg_JsonParserInit(json_parser);
    vnc_cfg_Server_ModuleInit(server->database(), server->graph());
    server->Initialize();
}

static bool OptionsParse(Options &options, int argc, char *argv[]) {
    try {
        options.Parse(*Dns::GetEventManager(), argc, argv);
        return true;
    } catch (boost::program_options::error &e) {
        cout << "Error " << e.what() << endl;
    } catch (...) {
        cout << "Options Parser: Caught fatal unknown exception" << endl;
    }

    return false;
}

void ReConfigSignalHandler(const boost::system::error_code &error, int sig) {
    if (error) {
        LOG(ERROR, "SIGHUP handler ERROR: " << error);
        return;
    }
    options.ParseReConfig();
}

int main(int argc, char *argv[]) {
    // Initialize the task scheduler
    int num_threads_to_tbb = TaskScheduler::GetDefaultThreadCount() +
        ConfigClientManager::GetNumWorkers();
    TaskScheduler::Initialize(num_threads_to_tbb);

    // Create DB table and event manager
    Dns::Init();

    // Process options from command-line and configuration file.
    if (!OptionsParse(options, argc, argv)) {
        exit(-1);
    }

    srand(unsigned(time(NULL)));
    std::vector<Signal::SignalHandler> sighup_handlers = boost::assign::list_of
        (boost::bind(&ReConfigSignalHandler, _1, _2));
    Signal::SignalCallbackMap smap = boost::assign::map_list_of
        (SIGHUP, sighup_handlers);
    Signal signal(Dns::GetEventManager(), smap);

    Dns::SetProgramName(argv[0]);
    Module::type module = Module::DNS;
    string module_name = g_vns_constants.ModuleNames.find(module)->second;

    std::string log_property_file = options.log_property_file();
    if (log_property_file.size()) {
        LoggingInit(log_property_file);
    }
    else {
        LoggingInit(options.log_file(), options.log_file_size(),
                    options.log_files_count(), options.use_syslog(),
                    options.syslog_facility(), module_name,
                    SandeshLevelTolog4Level(
                        Sandesh::StringToLevel(options.log_level())));
    }

    string build_info_str;
    Dns::GetVersion(build_info_str);
    MiscUtils::LogVersionInfo(build_info_str, Category::DNSAGENT);

    if (options.collectors_configured()) {
        Dns::SetCollector(options.collector_server_list()[0]);
    }
    Dns::SetHttpPort(options.http_server_port());
    Dns::SetDnsPort(options.dns_server_port());

    string hostname = options.hostname();
    Dns::SetHostName(hostname);

    ConnectionStateManager::GetInstance();
    NodeType::type node_type =
        g_vns_constants.Module2NodeType.find(module)->second;
    bool success(Sandesh::InitGenerator(
                 module_name,
                 options.hostname(),
                 g_vns_constants.NodeTypeNames.find(node_type)->second,
                 g_vns_constants.INSTANCE_ID_DEFAULT,
                 Dns::GetEventManager(),
                 options.http_server_port(),
                 options.randomized_collector_server_list(),
                 NULL,
                 Sandesh::DerivedStats(),
                 options.sandesh_config()));
    if (!success) {
        LOG(ERROR, "SANDESH: Initialization FAILED ... exiting");
        Sandesh::Uninit();
        exit(1);
    }
    Sandesh::SetLoggingParams(options.log_local(), options.log_category(),
                              options.log_level());

    // XXX Disable logging -- for test purposes only
    if (options.log_disable()) {
        SetLoggingDisabled(true);
    }

    // DNS::SetTestMode(options.test_mode());

    DB config_db(TaskScheduler::GetInstance()->GetTaskId("db::IFMapTable"));
    DBGraph config_graph;
    IFMapServer ifmap_server(&config_db, &config_graph,
                             Dns::GetEventManager()->io_service());

    ConfigFactory::Register<ConfigJsonParserBase>(
                          boost::factory<ConfigJsonParser *>());
    ConfigClientManager *config_client_manager =
        new ConfigClientManager(Dns::GetEventManager(), options.hostname(),
                  module_name, options.configdb_options());
    ConfigJsonParser *json_parser =
      static_cast<ConfigJsonParser *>(config_client_manager->config_json_parser());
    json_parser->ifmap_server_set(&ifmap_server);
    IFMap_Initialize(&ifmap_server, json_parser);

    DnsManager dns_manager;
    Dns::SetDnsManager(&dns_manager);
    dns_manager.Initialize(&config_db, &config_graph,
                           options.named_config_dir(),
                           options.named_config_file(),
                           options.named_log_file(),
                           options.rndc_config_file(),
                           options.rndc_secret(),
                           options.named_max_cache_size(),
                           options.named_max_retransmissions(),
                           options.named_retransmission_interval());
    DnsConfigParser parser(&config_db);
    parser.Parse(FileRead(options.config_file()));

    Dns::SetSelfIp(options.host_ip());
    if (!DnsAgentXmppManager::Init(options.xmpp_auth_enabled(),
                                   options.xmpp_server_cert(),
                                   options.xmpp_server_key(),
                                   options.xmpp_ca_cert())) {
        LOG(ERROR, "Address already in use " << ContrailPorts::DnsXmpp());
        exit(1);
    }

    XmppSandeshContext xmpp_sandesh_context;
    xmpp_sandesh_context.xmpp_server = Dns::GetXmppServer();
    Sandesh::set_module_context("XMPP", &xmpp_sandesh_context);
    IFMapSandeshContext ifmap_sandesh_context(&ifmap_server);
    Sandesh::set_module_context("IFMap", &ifmap_sandesh_context);

    start_time = UTCTimestampUsec();
    dns_info_trigger =
            new TaskTrigger(boost::bind(&DnsInfoLogger),
                    TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0);

    dns_info_log_timer =
        TimerManager::CreateTimer(*(Dns::GetEventManager()->io_service()),
                                                   "Dns Info log timer");
    dns_info_log_timer->Start(60*1000, boost::bind(&DnsInfoLogTimer), NULL);
    Dns::SetSelfIp(options.host_ip());
    ifmap_server.set_config_manager(config_client_manager);

    //
    // Determine if the number of connections is as expected.
    // 1. Cassandra Server
    // 2. AMQP Server
    //
    std::vector<ConnectionTypeName> expected_connections;
    expected_connections = boost::assign::list_of
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::COLLECTOR)->second, ""))
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::DATABASE)->second, "Cassandra"))
         (ConnectionTypeName(g_process_info_constants.ConnectionTypeNames.find(
                             ConnectionType::DATABASE)->second, "RabbitMQ"));

    ConnectionStateManager::GetInstance()->Init(
        *(Dns::GetEventManager()->io_service()), options.hostname(),
        module_name, g_vns_constants.INSTANCE_ID_DEFAULT,
        boost::bind(&DnsServerGetProcessStateCb, config_client_manager, _1, _2, _3,
                    expected_connections), "ObjectDns");

    dns_manager.set_config_manager(config_client_manager);
    options.set_config_client_manager(config_client_manager);
    config_client_manager->Initialize();

    Dns::GetEventManager()->Run();
    signal.Terminate();
    return 0;
}
<|endoftext|>