<commit_before>/**
 * @file directIOHelper.cc
 * @author Beata Skiba
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#ifdef linux
/* For pread()/pwrite()/utimensat() */
#define _XOPEN_SOURCE 700
#endif /* linux */

#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <sys/time.h>
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif

#include <limits.h>

#include "directIOHelper.h"

#include <iostream>

using namespace std;

namespace veil {
namespace helpers {

static char root_path[PATH_MAX];
static int root_path_len;

static void free_path(const char *path)
{
    free((void*) path);
}

const char * get_full_path(const char *path)
{
    int path_len = root_path_len + strlen(path) + 2;

    char * new_path = (char *)calloc(path_len, sizeof(char));

    memcpy(new_path, root_path, root_path_len);
    new_path[root_path_len] = '/';
    strcat(new_path, path);

    return new_path;
}

int DirectIOHelper::sh_getattr(const char *path, struct stat *stbuf)
{
    int res;
    path = get_full_path(path);
    res = lstat(path, stbuf);
    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

int DirectIOHelper::sh_access(const char *path, int mask)
{
    int res;
    path = get_full_path(path);

    res = access(path, mask);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_readlink(const char *path, char *buf, size_t size)
{
    int res;
    path = get_full_path(path);

    res = readlink(path, buf, size - 1);
    free_path(path);
    if (res == -1)
        return -errno;

    buf[res] = '\0';
    return 0;
}

int DirectIOHelper::sh_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
               off_t offset, struct fuse_file_info *fi)
{
    DIR *dp;
    struct dirent *de;

    (void) offset;
    (void) fi;
    path = get_full_path(path);

    dp = opendir(path);
    free_path(path);
    if (dp == NULL)
        return -errno;

    while ((de = readdir(dp)) != NULL) {
        struct stat st;
        memset(&st, 0, sizeof(st));
        st.st_ino = de->d_ino;
        st.st_mode = de->d_type << 12;
        if (filler(buf, de->d_name, &st, 0))
            break;
    }

    closedir(dp);
    return 0;
}

int DirectIOHelper::sh_mknod(const char *path, mode_t mode, dev_t rdev)
{
    int res;
    path = get_full_path(path);

    /* On Linux this could just be 'mknod(path, mode, rdev)' but this
       is more portable */
    if (S_ISREG(mode)) {
        res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
        if (res >= 0)
            res = close(res);
    } else if (S_ISFIFO(mode))
        res = mkfifo(path, mode);
    else
        res = mknod(path, mode, rdev);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_mkdir(const char *path, mode_t mode)
{
    int res;
    path = get_full_path(path);

    res = mkdir(path, mode);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_unlink(const char *path)
{
    int res;
    path = get_full_path(path);

    res = unlink(path);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_rmdir(const char *path)
{
    int res;
    path = get_full_path(path);

    res = rmdir(path);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_symlink(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = symlink(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_rename(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = rename(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_link(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = link(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_chmod(const char *path, mode_t mode)
{
    int res;
    path = get_full_path(path);

    res = chmod(path, mode);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_chown(const char *path, uid_t uid, gid_t gid)
{
    int res;
    path = get_full_path(path);

    res = lchown(path, uid, gid);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_truncate(const char *path, off_t size)
{
    int res;
    path = get_full_path(path);

    res = truncate(path, size);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

#ifdef HAVE_UTIMENSAT
int DirectIOHelper::sh_utimens(const char *path, const struct timespec ts[2])
{
    int res;
    path = get_full_path(path);

    /* don't use utime/utimes since they follow symlinks */
    res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}
#endif /* HAVE_UTIMENSAT */

int DirectIOHelper::sh_open(const char *path, struct fuse_file_info *fi)
{
    int res;
    path = get_full_path(path);

    res = open(path, fi->flags);

    free_path(path);
    if (res == -1)
        return -errno;

    fi->fh = res;

    return 0;
}

int DirectIOHelper::sh_read(const char *path, char *buf, size_t size, off_t offset,
            struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    if(fi->fh > 0)
        fd = fi->fh;
    else
        fd = open(path, O_RDONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = pread(fd, buf, size, offset);
    if (res == -1)
        res = -errno;

    if(fi->fh <= 0)
        close(fd);

    return res;
}

int DirectIOHelper::sh_write(const char *path, const char *buf, size_t size,
             off_t offset, struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    if(fi->fh > 0)
        fd = fi->fh;
    else
       fd = open(path, O_WRONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = pwrite(fd, buf, size, offset);
    if (res == -1)
        res = -errno;

    if(fi->fh <= 0)
        close(fd);

    return res;
}

int DirectIOHelper::sh_statfs(const char *path, struct statvfs *stbuf)
{
    int res;
    path = get_full_path(path);

    res = statvfs(path, stbuf);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_release(const char *path, struct fuse_file_info *fi)
{
    (void) path;

    if(fi->fh > 0)
       return close(fi->fh);
    else
       return 0;
}

int DirectIOHelper::sh_fsync(const char *path, int isdatasync,
             struct fuse_file_info *fi)
{
    /* Just a stub.     This method is optional and can safely be left
       unimplemented */

    (void) path;
    (void) isdatasync;
    (void) fi;
    return 0;
}

int DirectIOHelper::sh_flush(const char *path, struct fuse_file_info *fi)
{
    return 0;
}

#ifdef HAVE_POSIX_FALLOCATE
int DirectIOHelper::sh_fallocate(const char *path, int mode,
            off_t offset, off_t length, struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    (void) fi;

    if (mode)
        return -EOPNOTSUPP;

    fd = open(path, O_WRONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = -posix_fallocate(fd, offset, length);

    close(fd);
    return res;
}
#endif  /* HAVE_POSIX_FALLOCATE */

#ifdef HAVE_SETXATTR
/* xattr operations are optional and can safely be left unimplemented */
int DirectIOHelper::sh_setxattr(const char *path, const char *name, const char *value,
            size_t size, int flags)
{
    path = get_full_path(path);

    int res = lsetxattr(path, name, value, size, flags);

    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

int DirectIOHelper::sh_getxattr(const char *path, const char *name, char *value,
            size_t size)
{
    path = get_full_path(path);

    int res = lgetxattr(path, name, value, size);

    free_path(path);
    if (res == -1)
        return -errno;
    return res;
}

int DirectIOHelper::sh_listxattr(const char *path, char *list, size_t size)
{
    path = get_full_path(path);

    int res = llistxattr(path, list, size);

    free_path(path);
    if (res == -1)
        return -errno;
    return res;
}

int DirectIOHelper::sh_removexattr(const char *path, const char *name)
{
    path = get_full_path(path);

    int res = lremovexattr(path, name);

    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

#endif /* HAVE_SETXATTR */

DirectIOHelper::DirectIOHelper(const ArgsMap &args) {
    const auto rootPath = args.count("srv_arg1")
            ? boost::any_cast<std::string>(args.at("srv_arg1")) : std::string{};

    strncpy(root_path, rootPath.c_str(), PATH_MAX);
    root_path_len = strlen(root_path);
}

} // namespace helpers
} // namespace veil
<commit_msg>VFS-534 Fix arg numbering for DirectIO Helper.<commit_after>/**
 * @file directIOHelper.cc
 * @author Beata Skiba
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#ifdef linux
/* For pread()/pwrite()/utimensat() */
#define _XOPEN_SOURCE 700
#endif /* linux */

#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <sys/time.h>
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif

#include <limits.h>

#include "directIOHelper.h"

#include <iostream>

using namespace std;

namespace veil {
namespace helpers {

static char root_path[PATH_MAX];
static int root_path_len;

static void free_path(const char *path)
{
    free((void*) path);
}

const char * get_full_path(const char *path)
{
    int path_len = root_path_len + strlen(path) + 2;

    char * new_path = (char *)calloc(path_len, sizeof(char));

    memcpy(new_path, root_path, root_path_len);
    new_path[root_path_len] = '/';
    strcat(new_path, path);

    return new_path;
}

int DirectIOHelper::sh_getattr(const char *path, struct stat *stbuf)
{
    int res;
    path = get_full_path(path);
    res = lstat(path, stbuf);
    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

int DirectIOHelper::sh_access(const char *path, int mask)
{
    int res;
    path = get_full_path(path);

    res = access(path, mask);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_readlink(const char *path, char *buf, size_t size)
{
    int res;
    path = get_full_path(path);

    res = readlink(path, buf, size - 1);
    free_path(path);
    if (res == -1)
        return -errno;

    buf[res] = '\0';
    return 0;
}

int DirectIOHelper::sh_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
               off_t offset, struct fuse_file_info *fi)
{
    DIR *dp;
    struct dirent *de;

    (void) offset;
    (void) fi;
    path = get_full_path(path);

    dp = opendir(path);
    free_path(path);
    if (dp == NULL)
        return -errno;

    while ((de = readdir(dp)) != NULL) {
        struct stat st;
        memset(&st, 0, sizeof(st));
        st.st_ino = de->d_ino;
        st.st_mode = de->d_type << 12;
        if (filler(buf, de->d_name, &st, 0))
            break;
    }

    closedir(dp);
    return 0;
}

int DirectIOHelper::sh_mknod(const char *path, mode_t mode, dev_t rdev)
{
    int res;
    path = get_full_path(path);

    /* On Linux this could just be 'mknod(path, mode, rdev)' but this
       is more portable */
    if (S_ISREG(mode)) {
        res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
        if (res >= 0)
            res = close(res);
    } else if (S_ISFIFO(mode))
        res = mkfifo(path, mode);
    else
        res = mknod(path, mode, rdev);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_mkdir(const char *path, mode_t mode)
{
    int res;
    path = get_full_path(path);

    res = mkdir(path, mode);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_unlink(const char *path)
{
    int res;
    path = get_full_path(path);

    res = unlink(path);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_rmdir(const char *path)
{
    int res;
    path = get_full_path(path);

    res = rmdir(path);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_symlink(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = symlink(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_rename(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = rename(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_link(const char *from, const char *to)
{
    int res;
    from = get_full_path(from);
    to = get_full_path(to);

    res = link(from, to);
    free_path(from);
    free_path(to);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_chmod(const char *path, mode_t mode)
{
    int res;
    path = get_full_path(path);

    res = chmod(path, mode);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_chown(const char *path, uid_t uid, gid_t gid)
{
    int res;
    path = get_full_path(path);

    res = lchown(path, uid, gid);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_truncate(const char *path, off_t size)
{
    int res;
    path = get_full_path(path);

    res = truncate(path, size);
    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

#ifdef HAVE_UTIMENSAT
int DirectIOHelper::sh_utimens(const char *path, const struct timespec ts[2])
{
    int res;
    path = get_full_path(path);

    /* don't use utime/utimes since they follow symlinks */
    res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}
#endif /* HAVE_UTIMENSAT */

int DirectIOHelper::sh_open(const char *path, struct fuse_file_info *fi)
{
    int res;
    path = get_full_path(path);

    res = open(path, fi->flags);

    free_path(path);
    if (res == -1)
        return -errno;

    fi->fh = res;

    return 0;
}

int DirectIOHelper::sh_read(const char *path, char *buf, size_t size, off_t offset,
            struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    if(fi->fh > 0)
        fd = fi->fh;
    else
        fd = open(path, O_RDONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = pread(fd, buf, size, offset);
    if (res == -1)
        res = -errno;

    if(fi->fh <= 0)
        close(fd);

    return res;
}

int DirectIOHelper::sh_write(const char *path, const char *buf, size_t size,
             off_t offset, struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    if(fi->fh > 0)
        fd = fi->fh;
    else
       fd = open(path, O_WRONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = pwrite(fd, buf, size, offset);
    if (res == -1)
        res = -errno;

    if(fi->fh <= 0)
        close(fd);

    return res;
}

int DirectIOHelper::sh_statfs(const char *path, struct statvfs *stbuf)
{
    int res;
    path = get_full_path(path);

    res = statvfs(path, stbuf);

    free_path(path);
    if (res == -1)
        return -errno;

    return 0;
}

int DirectIOHelper::sh_release(const char *path, struct fuse_file_info *fi)
{
    (void) path;

    if(fi->fh > 0)
       return close(fi->fh);
    else
       return 0;
}

int DirectIOHelper::sh_fsync(const char *path, int isdatasync,
             struct fuse_file_info *fi)
{
    /* Just a stub.     This method is optional and can safely be left
       unimplemented */

    (void) path;
    (void) isdatasync;
    (void) fi;
    return 0;
}

int DirectIOHelper::sh_flush(const char *path, struct fuse_file_info *fi)
{
    return 0;
}

#ifdef HAVE_POSIX_FALLOCATE
int DirectIOHelper::sh_fallocate(const char *path, int mode,
            off_t offset, off_t length, struct fuse_file_info *fi)
{
    int fd;
    int res;
    path = get_full_path(path);

    (void) fi;

    if (mode)
        return -EOPNOTSUPP;

    fd = open(path, O_WRONLY);

    free_path(path);
    if (fd == -1)
        return -errno;

    res = -posix_fallocate(fd, offset, length);

    close(fd);
    return res;
}
#endif  /* HAVE_POSIX_FALLOCATE */

#ifdef HAVE_SETXATTR
/* xattr operations are optional and can safely be left unimplemented */
int DirectIOHelper::sh_setxattr(const char *path, const char *name, const char *value,
            size_t size, int flags)
{
    path = get_full_path(path);

    int res = lsetxattr(path, name, value, size, flags);

    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

int DirectIOHelper::sh_getxattr(const char *path, const char *name, char *value,
            size_t size)
{
    path = get_full_path(path);

    int res = lgetxattr(path, name, value, size);

    free_path(path);
    if (res == -1)
        return -errno;
    return res;
}

int DirectIOHelper::sh_listxattr(const char *path, char *list, size_t size)
{
    path = get_full_path(path);

    int res = llistxattr(path, list, size);

    free_path(path);
    if (res == -1)
        return -errno;
    return res;
}

int DirectIOHelper::sh_removexattr(const char *path, const char *name)
{
    path = get_full_path(path);

    int res = lremovexattr(path, name);

    free_path(path);
    if (res == -1)
        return -errno;
    return 0;
}

#endif /* HAVE_SETXATTR */

DirectIOHelper::DirectIOHelper(const ArgsMap &args) {
    const auto rootPath = args.count("srv_arg0")
            ? boost::any_cast<std::string>(args.at("srv_arg0")) : std::string{};

    strncpy(root_path, rootPath.c_str(), PATH_MAX);
    root_path_len = strlen(root_path);
}

} // namespace helpers
} // namespace veil
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "disk_interface.h"

#include <algorithm>

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#include <windows.h>
#include <direct.h>  // _mkdir
#endif

#include "util.h"

namespace {

string DirName(const string& path) {
#ifdef _WIN32
  const char kPathSeparators[] = "\\/";
#else
  const char kPathSeparators[] = "/";
#endif
  string::size_type slash_pos = path.find_last_of(kPathSeparators);
  if (slash_pos == string::npos)
    return string();  // Nothing to do.
  const char* const kEnd = kPathSeparators + strlen(kPathSeparators);
  while (slash_pos > 0 &&
         std::find(kPathSeparators, kEnd, path[slash_pos - 1]) != kEnd)
    --slash_pos;
  return path.substr(0, slash_pos);
}

int MakeDir(const string& path) {
#ifdef _WIN32
  return _mkdir(path.c_str());
#else
  return mkdir(path.c_str(), 0777);
#endif
}

#ifdef _WIN32
TimeStamp TimeStampFromFileTime(const FILETIME& filetime) {
  // FILETIME is in 100-nanosecond increments since the Windows epoch.
  // We don't much care about epoch correctness but we do want the
  // resulting value to fit in an integer.
  uint64_t mtime = ((uint64_t)filetime.dwHighDateTime << 32) |
    ((uint64_t)filetime.dwLowDateTime);
  mtime /= 1000000000LL / 100; // 100ns -> s.
  mtime -= 12622770400LL;  // 1600 epoch -> 2000 epoch (subtract 400 years).
  return (TimeStamp)mtime;
}

TimeStamp StatSingleFile(const string& path, bool quiet) {
  WIN32_FILE_ATTRIBUTE_DATA attrs;
  if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &attrs)) {
    DWORD err = GetLastError();
    if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
      return 0;
    if (!quiet) {
      Error("GetFileAttributesEx(%s): %s", path.c_str(),
            GetLastErrorString().c_str());
    }
    return -1;
  }
  return TimeStampFromFileTime(attrs.ftLastWriteTime);
}

#pragma warning(push)
#pragma warning(disable: 4996)  // GetVersionExA is deprecated post SDK 8.1.
bool IsWindows7OrLater() {
  OSVERSIONINFO version_info = { sizeof(version_info) };
  if (!GetVersionEx(&version_info))
    Fatal("GetVersionEx: %s", GetLastErrorString().c_str());
  return version_info.dwMajorVersion > 6 ||
         version_info.dwMajorVersion == 6 && version_info.dwMinorVersion >= 1;
}
#pragma warning(pop)

bool StatAllFilesInDir(const string& dir, map<string, TimeStamp>* stamps,
                       bool quiet) {
  // FindExInfoBasic is 30% faster than FindExInfoStandard.
  static bool can_use_basic_info = IsWindows7OrLater();
  // This is not in earlier SDKs.
  const FINDEX_INFO_LEVELS kFindExInfoBasic =
      static_cast<FINDEX_INFO_LEVELS>(1);
  FINDEX_INFO_LEVELS level =
      can_use_basic_info ? kFindExInfoBasic : FindExInfoStandard;
  WIN32_FIND_DATAA ffd;
  HANDLE find_handle = FindFirstFileExA((dir + "\\*").c_str(), level, &ffd,
                                        FindExSearchNameMatch, NULL, 0);

  if (find_handle == INVALID_HANDLE_VALUE) {
    DWORD err = GetLastError();
    if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
      return true;
    if (!quiet) {
      Error("FindFirstFileExA(%s): %s", dir.c_str(),
            GetLastErrorString().c_str());
    }
    return false;
  }
  do {
    string lowername = ffd.cFileName;
    transform(lowername.begin(), lowername.end(), lowername.begin(), ::tolower);
    stamps->insert(make_pair(lowername,
                             TimeStampFromFileTime(ffd.ftLastWriteTime)));
  } while (FindNextFileA(find_handle, &ffd));
  FindClose(find_handle);
  return true;
}
#endif  // _WIN32

}  // namespace

// DiskInterface ---------------------------------------------------------------

bool DiskInterface::MakeDirs(const string& path) {
  string dir = DirName(path);
  if (dir.empty())
    return true;  // Reached root; assume it's there.
  TimeStamp mtime = Stat(dir);
  if (mtime < 0)
    return false;  // Error.
  if (mtime > 0)
    return true;  // Exists already; we're done.

  // Directory doesn't exist.  Try creating its parent first.
  bool success = MakeDirs(dir);
  if (!success)
    return false;
  return MakeDir(dir);
}

// RealDiskInterface -----------------------------------------------------------

TimeStamp RealDiskInterface::Stat(const string& path) const {
#ifdef _WIN32
  // MSDN: "Naming Files, Paths, and Namespaces"
  // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
  if (!path.empty() && path[0] != '\\' && path.size() > MAX_PATH) {
    if (!quiet_) {
      Error("Stat(%s): Filename longer than %i characters",
            path.c_str(), MAX_PATH);
    }
    return -1;
  }
  if (!use_cache_)
    return StatSingleFile(path, quiet_);

  string dir = DirName(path);
  string base(path.substr(dir.size() ? dir.size() + 1 : 0));

  transform(dir.begin(), dir.end(), dir.begin(), ::tolower);
  transform(base.begin(), base.end(), base.begin(), ::tolower);

  Cache::iterator ci = cache_.find(dir);
  if (ci == cache_.end()) {
    ci = cache_.insert(make_pair(dir, DirCache())).first;
    if (!StatAllFilesInDir(dir.empty() ? "." : dir, &ci->second, quiet_)) {
      cache_.erase(ci);
      return -1;
    }
  }
  DirCache::iterator di = ci->second.find(base);
  return di != ci->second.end() ? di->second : 0;
#else
  struct stat st;
  if (stat(path.c_str(), &st) < 0) {
    if (errno == ENOENT || errno == ENOTDIR)
      return 0;
    if (!quiet_) {
      Error("stat(%s): %s", path.c_str(), strerror(errno));
    }
    return -1;
  }
  return st.st_mtime;
#endif
}

bool RealDiskInterface::WriteFile(const string& path, const string& contents) {
  FILE* fp = fopen(path.c_str(), "w");
  if (fp == NULL) {
    Error("WriteFile(%s): Unable to create file. %s",
          path.c_str(), strerror(errno));
    return false;
  }

  if (fwrite(contents.data(), 1, contents.length(), fp) < contents.length())  {
    Error("WriteFile(%s): Unable to write to the file. %s",
          path.c_str(), strerror(errno));
    fclose(fp);
    return false;
  }

  if (fclose(fp) == EOF) {
    Error("WriteFile(%s): Unable to close the file. %s",
          path.c_str(), strerror(errno));
    return false;
  }

  return true;
}

bool RealDiskInterface::MakeDir(const string& path) {
  if (::MakeDir(path) < 0) {
    if (errno == EEXIST) {
      return true;
    }
    Error("mkdir(%s): %s", path.c_str(), strerror(errno));
    return false;
  }
  return true;
}

string RealDiskInterface::ReadFile(const string& path, string* err) {
  string contents;
  int ret = ::ReadFile(path, &contents, err);
  if (ret == -ENOENT) {
    // Swallow ENOENT.
    err->clear();
  }
  return contents;
}

int RealDiskInterface::RemoveFile(const string& path) {
  if (remove(path.c_str()) < 0) {
    switch (errno) {
      case ENOENT:
        return 1;
      default:
        Error("remove(%s): %s", path.c_str(), strerror(errno));
        return -1;
    }
  } else {
    return 0;
  }
}

void RealDiskInterface::AllowStatCache(bool allow) {
#ifdef _WIN32
  use_cache_ = allow;
  if (!use_cache_)
    cache_.clear();
#endif
}
<commit_msg>add some parens to silence a gcc warning<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "disk_interface.h"

#include <algorithm>

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#include <windows.h>
#include <direct.h>  // _mkdir
#endif

#include "util.h"

namespace {

string DirName(const string& path) {
#ifdef _WIN32
  const char kPathSeparators[] = "\\/";
#else
  const char kPathSeparators[] = "/";
#endif
  string::size_type slash_pos = path.find_last_of(kPathSeparators);
  if (slash_pos == string::npos)
    return string();  // Nothing to do.
  const char* const kEnd = kPathSeparators + strlen(kPathSeparators);
  while (slash_pos > 0 &&
         std::find(kPathSeparators, kEnd, path[slash_pos - 1]) != kEnd)
    --slash_pos;
  return path.substr(0, slash_pos);
}

int MakeDir(const string& path) {
#ifdef _WIN32
  return _mkdir(path.c_str());
#else
  return mkdir(path.c_str(), 0777);
#endif
}

#ifdef _WIN32
TimeStamp TimeStampFromFileTime(const FILETIME& filetime) {
  // FILETIME is in 100-nanosecond increments since the Windows epoch.
  // We don't much care about epoch correctness but we do want the
  // resulting value to fit in an integer.
  uint64_t mtime = ((uint64_t)filetime.dwHighDateTime << 32) |
    ((uint64_t)filetime.dwLowDateTime);
  mtime /= 1000000000LL / 100; // 100ns -> s.
  mtime -= 12622770400LL;  // 1600 epoch -> 2000 epoch (subtract 400 years).
  return (TimeStamp)mtime;
}

TimeStamp StatSingleFile(const string& path, bool quiet) {
  WIN32_FILE_ATTRIBUTE_DATA attrs;
  if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &attrs)) {
    DWORD err = GetLastError();
    if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
      return 0;
    if (!quiet) {
      Error("GetFileAttributesEx(%s): %s", path.c_str(),
            GetLastErrorString().c_str());
    }
    return -1;
  }
  return TimeStampFromFileTime(attrs.ftLastWriteTime);
}

#pragma warning(push)
#pragma warning(disable: 4996)  // GetVersionExA is deprecated post SDK 8.1.
bool IsWindows7OrLater() {
  OSVERSIONINFO version_info = { sizeof(version_info) };
  if (!GetVersionEx(&version_info))
    Fatal("GetVersionEx: %s", GetLastErrorString().c_str());
  return version_info.dwMajorVersion > 6 ||
         (version_info.dwMajorVersion == 6 && version_info.dwMinorVersion >= 1);
}
#pragma warning(pop)

bool StatAllFilesInDir(const string& dir, map<string, TimeStamp>* stamps,
                       bool quiet) {
  // FindExInfoBasic is 30% faster than FindExInfoStandard.
  static bool can_use_basic_info = IsWindows7OrLater();
  // This is not in earlier SDKs.
  const FINDEX_INFO_LEVELS kFindExInfoBasic =
      static_cast<FINDEX_INFO_LEVELS>(1);
  FINDEX_INFO_LEVELS level =
      can_use_basic_info ? kFindExInfoBasic : FindExInfoStandard;
  WIN32_FIND_DATAA ffd;
  HANDLE find_handle = FindFirstFileExA((dir + "\\*").c_str(), level, &ffd,
                                        FindExSearchNameMatch, NULL, 0);

  if (find_handle == INVALID_HANDLE_VALUE) {
    DWORD err = GetLastError();
    if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
      return true;
    if (!quiet) {
      Error("FindFirstFileExA(%s): %s", dir.c_str(),
            GetLastErrorString().c_str());
    }
    return false;
  }
  do {
    string lowername = ffd.cFileName;
    transform(lowername.begin(), lowername.end(), lowername.begin(), ::tolower);
    stamps->insert(make_pair(lowername,
                             TimeStampFromFileTime(ffd.ftLastWriteTime)));
  } while (FindNextFileA(find_handle, &ffd));
  FindClose(find_handle);
  return true;
}
#endif  // _WIN32

}  // namespace

// DiskInterface ---------------------------------------------------------------

bool DiskInterface::MakeDirs(const string& path) {
  string dir = DirName(path);
  if (dir.empty())
    return true;  // Reached root; assume it's there.
  TimeStamp mtime = Stat(dir);
  if (mtime < 0)
    return false;  // Error.
  if (mtime > 0)
    return true;  // Exists already; we're done.

  // Directory doesn't exist.  Try creating its parent first.
  bool success = MakeDirs(dir);
  if (!success)
    return false;
  return MakeDir(dir);
}

// RealDiskInterface -----------------------------------------------------------

TimeStamp RealDiskInterface::Stat(const string& path) const {
#ifdef _WIN32
  // MSDN: "Naming Files, Paths, and Namespaces"
  // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
  if (!path.empty() && path[0] != '\\' && path.size() > MAX_PATH) {
    if (!quiet_) {
      Error("Stat(%s): Filename longer than %i characters",
            path.c_str(), MAX_PATH);
    }
    return -1;
  }
  if (!use_cache_)
    return StatSingleFile(path, quiet_);

  string dir = DirName(path);
  string base(path.substr(dir.size() ? dir.size() + 1 : 0));

  transform(dir.begin(), dir.end(), dir.begin(), ::tolower);
  transform(base.begin(), base.end(), base.begin(), ::tolower);

  Cache::iterator ci = cache_.find(dir);
  if (ci == cache_.end()) {
    ci = cache_.insert(make_pair(dir, DirCache())).first;
    if (!StatAllFilesInDir(dir.empty() ? "." : dir, &ci->second, quiet_)) {
      cache_.erase(ci);
      return -1;
    }
  }
  DirCache::iterator di = ci->second.find(base);
  return di != ci->second.end() ? di->second : 0;
#else
  struct stat st;
  if (stat(path.c_str(), &st) < 0) {
    if (errno == ENOENT || errno == ENOTDIR)
      return 0;
    if (!quiet_) {
      Error("stat(%s): %s", path.c_str(), strerror(errno));
    }
    return -1;
  }
  return st.st_mtime;
#endif
}

bool RealDiskInterface::WriteFile(const string& path, const string& contents) {
  FILE* fp = fopen(path.c_str(), "w");
  if (fp == NULL) {
    Error("WriteFile(%s): Unable to create file. %s",
          path.c_str(), strerror(errno));
    return false;
  }

  if (fwrite(contents.data(), 1, contents.length(), fp) < contents.length())  {
    Error("WriteFile(%s): Unable to write to the file. %s",
          path.c_str(), strerror(errno));
    fclose(fp);
    return false;
  }

  if (fclose(fp) == EOF) {
    Error("WriteFile(%s): Unable to close the file. %s",
          path.c_str(), strerror(errno));
    return false;
  }

  return true;
}

bool RealDiskInterface::MakeDir(const string& path) {
  if (::MakeDir(path) < 0) {
    if (errno == EEXIST) {
      return true;
    }
    Error("mkdir(%s): %s", path.c_str(), strerror(errno));
    return false;
  }
  return true;
}

string RealDiskInterface::ReadFile(const string& path, string* err) {
  string contents;
  int ret = ::ReadFile(path, &contents, err);
  if (ret == -ENOENT) {
    // Swallow ENOENT.
    err->clear();
  }
  return contents;
}

int RealDiskInterface::RemoveFile(const string& path) {
  if (remove(path.c_str()) < 0) {
    switch (errno) {
      case ENOENT:
        return 1;
      default:
        Error("remove(%s): %s", path.c_str(), strerror(errno));
        return -1;
    }
  } else {
    return 0;
  }
}

void RealDiskInterface::AllowStatCache(bool allow) {
#ifdef _WIN32
  use_cache_ = allow;
  if (!use_cache_)
    cache_.clear();
#endif
}
<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE
 */

#include <eosio/chain/protocol_feature_manager.hpp>
#include <eosio/chain/exceptions.hpp>

#include <algorithm>
#include <boost/assign/list_of.hpp>

namespace eosio { namespace chain {

   const std::unordered_map<builtin_protocol_feature_t, builtin_protocol_feature_spec, enum_hash<builtin_protocol_feature_t>>
   builtin_protocol_feature_codenames =
      boost::assign::map_list_of<builtin_protocol_feature_t, builtin_protocol_feature_spec>
         ( builtin_protocol_feature_t::preactivate_feature, {
            "PREACTIVATE_FEATURE",
            digest_type{},
            {},
            {time_point{}, false, true} // enabled without preactivation and ready to go at any time
         } )
   ;

   const char* builtin_protocol_feature_codename( builtin_protocol_feature_t codename ) {
      auto itr = builtin_protocol_feature_codenames.find( codename );
      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t passed to builtin_protocol_feature_codename: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      return itr->second.codename;
   }

   protocol_feature_base::protocol_feature_base( protocol_feature_t feature_type,
                                                 const digest_type& description_digest,
                                                 flat_set<digest_type>&& dependencies,
                                                 const protocol_feature_subjective_restrictions& restrictions )
   :description_digest( description_digest )
   ,dependencies( std::move(dependencies) )
   ,subjective_restrictions( restrictions )
   ,_type( feature_type )
   {
      switch( feature_type ) {
         case protocol_feature_t::builtin:
            protocol_feature_type = builtin_protocol_feature::feature_type_string;
         break;
         default:
         {
            EOS_THROW( protocol_feature_validation_exception,
                       "Unsupported protocol_feature_t passed to constructor: ${type}",
                       ("type", static_cast<uint32_t>(feature_type)) );
         }
         break;
      }
   }

   void protocol_feature_base::reflector_init() {
      static_assert( fc::raw::has_feature_reflector_init_on_unpacked_reflected_types,
                     "protocol_feature_activation expects FC to support reflector_init" );

      if( protocol_feature_type == builtin_protocol_feature::feature_type_string ) {
         _type = protocol_feature_t::builtin;
      } else {
         EOS_THROW( protocol_feature_validation_exception,
                    "Unsupported protocol feature type: ${type}", ("type", protocol_feature_type) );
      }
   }

   builtin_protocol_feature::builtin_protocol_feature( builtin_protocol_feature_t codename,
                                                       const digest_type& description_digest,
                                                       flat_set<digest_type>&& dependencies,
                                                       const protocol_feature_subjective_restrictions& restrictions )
   :protocol_feature_base( protocol_feature_t::builtin, description_digest, std::move(dependencies), restrictions )
   ,_codename(codename)
   {
      auto itr = builtin_protocol_feature_codenames.find( codename );
      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t passed to constructor: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      builtin_feature_codename = itr->second.codename;
   }

   void builtin_protocol_feature::reflector_init() {
      protocol_feature_base::reflector_init();

      for( const auto& p : builtin_protocol_feature_codenames ) {
         if( builtin_feature_codename.compare( p.second.codename ) == 0 ) {
            _codename = p.first;
            return;
         }
      }

      EOS_THROW( protocol_feature_validation_exception,
                 "Unsupported builtin protocol feature codename: ${codename}",
                 ("codename", builtin_feature_codename) );
   }

   digest_type builtin_protocol_feature::digest()const {
      digest_type::encoder enc;
      fc::raw::pack( enc, _type );
      fc::raw::pack( enc, description_digest  );
      fc::raw::pack( enc, _codename );

      return enc.result();
   }

   protocol_feature_manager::protocol_feature_manager() {
      _builtin_protocol_features.reserve( builtin_protocol_feature_codenames.size() );
   }

   protocol_feature_manager::recognized_t
   protocol_feature_manager::is_recognized( const digest_type& feature_digest, time_point now )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      if( itr == _recognized_protocol_features.end() )
         return recognized_t::unrecognized;

      if( !itr->enabled )
         return recognized_t::disabled;

      if( itr->earliest_allowed_activation_time > now )
         return recognized_t::too_early;

      if( itr->preactivation_required )
         return recognized_t::ready_if_preactivated;

      return recognized_t::ready;
   }

   const protocol_feature_manager::protocol_feature&
   protocol_feature_manager::get_protocol_feature( const digest_type& feature_digest )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
                  "unrecognized protocol feature with digest: ${digest}",
                  ("digest", feature_digest)
      );

      return *itr;
   }

   bool protocol_feature_manager::is_builtin_activated( builtin_protocol_feature_t feature_codename,
                                                        uint32_t current_block_num )const
   {
      uint32_t indx = static_cast<uint32_t>( feature_codename );

      if( indx >= _builtin_protocol_features.size() ) return false;

      return (_builtin_protocol_features[indx].activation_block_num <= current_block_num);
   }

   optional<digest_type>
   protocol_feature_manager::get_builtin_digest( builtin_protocol_feature_t feature_codename )const
   {
      uint32_t indx = static_cast<uint32_t>( feature_codename );

      if( indx >= _builtin_protocol_features.size() )
         return {};

      if( _builtin_protocol_features[indx].iterator_to_protocol_feature == _recognized_protocol_features.end() )
         return {};

      return _builtin_protocol_features[indx].iterator_to_protocol_feature->feature_digest;
   }

   bool protocol_feature_manager::validate_dependencies(
                                    const digest_type& feature_digest,
                                    const std::function<bool(const digest_type&)>& validator
   )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      if( itr == _recognized_protocol_features.end() ) return false;

      for( const auto& d : itr->dependencies ) {
         if( !validator(d) ) return false;
      }

      return true;
   }

   builtin_protocol_feature
   protocol_feature_manager::make_default_builtin_protocol_feature(
      builtin_protocol_feature_t codename,
      const std::function<void(builtin_protocol_feature_t dependency)>& handle_dependency
   )const {
      auto itr = builtin_protocol_feature_codenames.find( codename );

      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      flat_set<digest_type> dependencies;
      dependencies.reserve( itr->second.builtin_dependencies.size() );

      for( const auto& d : itr->second.builtin_dependencies ) {
         handle_dependency( d );
         auto dependency_digest = get_builtin_digest( d );
         EOS_ASSERT( dependency_digest, protocol_feature_exception,
                     "cannot make default builtin protocol feature with codename '${codename}' since it has a dependency that has not been added yet: ${dependency_codename}",
                     ("codename", static_cast<uint32_t>(itr->first))
                     ("dependency_codename", static_cast<uint32_t>(d))
         );
         dependencies.insert( *dependency_digest );
      }

      return {itr->first, itr->second.description_digest, std::move(dependencies), itr->second.subjective_restrictions};
   }

   void protocol_feature_manager::add_feature( const builtin_protocol_feature& f ) {
      EOS_ASSERT( _head_of_builtin_activation_list == builtin_protocol_feature_entry::no_previous,
                  protocol_feature_exception,
                  "new builtin protocol features cannot be added after a protocol feature has already been activated" );

      auto builtin_itr = builtin_protocol_feature_codenames.find( f._codename );
      EOS_ASSERT( builtin_itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Builtin protocol feature has unsupported builtin_protocol_feature_t: ${codename}",
                  ("codename", static_cast<uint32_t>( f._codename )) );

      uint32_t indx = static_cast<uint32_t>( f._codename );

      if( indx < _builtin_protocol_features.size() ) {
         EOS_ASSERT( _builtin_protocol_features[indx].iterator_to_protocol_feature == _recognized_protocol_features.end(),
                     protocol_feature_exception,
                     "builtin protocol feature with codename '${codename}' already added",
                     ("codename", f.builtin_feature_codename) );
      }

      auto feature_digest = f.digest();

      const auto& expected_builtin_dependencies = builtin_itr->second.builtin_dependencies;
      flat_set<builtin_protocol_feature_t> satisfied_builtin_dependencies;
      satisfied_builtin_dependencies.reserve( expected_builtin_dependencies.size() );

      for( const auto& d : f.dependencies ) {
         auto itr = _recognized_protocol_features.find( d );
         EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
            "builtin protocol feature with codename '${codename}' and digest of ${digest} has a dependency on a protocol feature with digest ${dependency_digest} that is not recognized",
            ("codename", f.builtin_feature_codename)
            ("digest",  feature_digest)
            ("dependency_digest", d )
         );

         if( itr->builtin_feature
             && expected_builtin_dependencies.find( *itr->builtin_feature )
                  != expected_builtin_dependencies.end() )
         {
            satisfied_builtin_dependencies.insert( *itr->builtin_feature );
         }
      }

      if( expected_builtin_dependencies.size() > satisfied_builtin_dependencies.size() ) {
         flat_set<builtin_protocol_feature_t> missing_builtins;
         missing_builtins.reserve( expected_builtin_dependencies.size() - satisfied_builtin_dependencies.size() );
         std::set_difference( expected_builtin_dependencies.begin(), expected_builtin_dependencies.end(),
                              satisfied_builtin_dependencies.begin(), satisfied_builtin_dependencies.end(),
                              end_inserter( missing_builtins )
         );

         vector<string> missing_builtins_with_names;
         missing_builtins_with_names.reserve( missing_builtins.size() );
         for( const auto& builtin_codename : missing_builtins ) {
            auto itr = builtin_protocol_feature_codenames.find( builtin_codename );
            EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(),
                        protocol_feature_exception,
                        "Unexpected error"
            );
            missing_builtins_with_names.emplace_back( itr->second.codename );
         }

         EOS_THROW(  protocol_feature_validation_exception,
                     "Not all the builtin dependencies of the builtin protocol feature with codename '${codename}' and digest of ${digest} were satisfied.",
                     ("missing_dependencies", missing_builtins_with_names)
         );
      }

      auto res = _recognized_protocol_features.insert( protocol_feature{
         feature_digest,
         f.dependencies,
         f.subjective_restrictions.earliest_allowed_activation_time,
         f.subjective_restrictions.preactivation_required,
         f.subjective_restrictions.enabled,
         f._codename
      } );

      EOS_ASSERT( res.second, protocol_feature_exception,
                  "builtin protocol feature with codename '${codename}' has a digest of ${digest} but another protocol feature with the same digest has already been added",
                  ("codename", f.builtin_feature_codename)("digest", feature_digest) );

      if( indx < _builtin_protocol_features.size() ) {
         for( auto i =_builtin_protocol_features.size(); i <= indx; ++i ) {
            _builtin_protocol_features.push_back( builtin_protocol_feature_entry{
                                                   _recognized_protocol_features.end(),
                                                   builtin_protocol_feature_entry::not_active
                                                  } );
         }
      }

      _builtin_protocol_features[indx].iterator_to_protocol_feature = res.first;
   }

   void protocol_feature_manager::activate_feature( const digest_type& feature_digest,
                                                    uint32_t current_block_num )
   {
      auto itr = _recognized_protocol_features.find( feature_digest );

      EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
                  "unrecognized protocol feature digest: ${digest}", ("digest", feature_digest) );

      if( itr->builtin_feature ) {
         if( _head_of_builtin_activation_list != builtin_protocol_feature_entry::no_previous ) {
            auto largest_block_num_of_activated_builtins = _builtin_protocol_features[_head_of_builtin_activation_list].activation_block_num;
            EOS_ASSERT( largest_block_num_of_activated_builtins <= current_block_num,
                        protocol_feature_exception,
                        "trying to activate a builtin protocol feature with a current block number of "
                        "${current_block_num} when the largest activation block number of all activated builtin "
                        "protocol features is ${largest_block_num_of_activated_builtins}",
                        ("current_block_num", current_block_num)
                        ("largest_block_num_of_activated_builtins", largest_block_num_of_activated_builtins)
            );
         }

         uint32_t indx = static_cast<uint32_t>( *itr->builtin_feature );

         EOS_ASSERT( indx < _builtin_protocol_features.size() &&
                     _builtin_protocol_features[indx].iterator_to_protocol_feature != _recognized_protocol_features.end(),
                     protocol_feature_exception,
                     "invariant failure: problem with activating builtin protocol feature with digest: ${digest}",
                     ("digest", feature_digest) );

         EOS_ASSERT( _builtin_protocol_features[indx].activation_block_num == builtin_protocol_feature_entry::not_active,
                     protocol_feature_exception,
                     "cannot activate already activated builtin feature with digest: ${digest}",
                     ("digest", feature_digest) );

         _builtin_protocol_features[indx].activation_block_num = current_block_num;
         _builtin_protocol_features[indx].previous = _head_of_builtin_activation_list;
         _head_of_builtin_activation_list = indx;
      }
   }

   void protocol_feature_manager::popped_blocks_to( uint32_t block_num ) {
      while( _head_of_builtin_activation_list != builtin_protocol_feature_entry::no_previous ) {
         auto& e = _builtin_protocol_features[_head_of_builtin_activation_list];
         if( e.activation_block_num <= block_num ) break;

         _head_of_builtin_activation_list = e.previous;
         e.activation_block_num = builtin_protocol_feature_entry::not_active;
         e.previous = builtin_protocol_feature_entry::no_previous;
      }
   }

} }  // eosio::chain
<commit_msg>add dependencies to hash that generates feature digest<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE
 */

#include <eosio/chain/protocol_feature_manager.hpp>
#include <eosio/chain/exceptions.hpp>

#include <algorithm>
#include <boost/assign/list_of.hpp>

namespace eosio { namespace chain {

   const std::unordered_map<builtin_protocol_feature_t, builtin_protocol_feature_spec, enum_hash<builtin_protocol_feature_t>>
   builtin_protocol_feature_codenames =
      boost::assign::map_list_of<builtin_protocol_feature_t, builtin_protocol_feature_spec>
         ( builtin_protocol_feature_t::preactivate_feature, {
            "PREACTIVATE_FEATURE",
            digest_type{},
            {},
            {time_point{}, false, true} // enabled without preactivation and ready to go at any time
         } )
   ;

   const char* builtin_protocol_feature_codename( builtin_protocol_feature_t codename ) {
      auto itr = builtin_protocol_feature_codenames.find( codename );
      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t passed to builtin_protocol_feature_codename: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      return itr->second.codename;
   }

   protocol_feature_base::protocol_feature_base( protocol_feature_t feature_type,
                                                 const digest_type& description_digest,
                                                 flat_set<digest_type>&& dependencies,
                                                 const protocol_feature_subjective_restrictions& restrictions )
   :description_digest( description_digest )
   ,dependencies( std::move(dependencies) )
   ,subjective_restrictions( restrictions )
   ,_type( feature_type )
   {
      switch( feature_type ) {
         case protocol_feature_t::builtin:
            protocol_feature_type = builtin_protocol_feature::feature_type_string;
         break;
         default:
         {
            EOS_THROW( protocol_feature_validation_exception,
                       "Unsupported protocol_feature_t passed to constructor: ${type}",
                       ("type", static_cast<uint32_t>(feature_type)) );
         }
         break;
      }
   }

   void protocol_feature_base::reflector_init() {
      static_assert( fc::raw::has_feature_reflector_init_on_unpacked_reflected_types,
                     "protocol_feature_activation expects FC to support reflector_init" );

      if( protocol_feature_type == builtin_protocol_feature::feature_type_string ) {
         _type = protocol_feature_t::builtin;
      } else {
         EOS_THROW( protocol_feature_validation_exception,
                    "Unsupported protocol feature type: ${type}", ("type", protocol_feature_type) );
      }
   }

   builtin_protocol_feature::builtin_protocol_feature( builtin_protocol_feature_t codename,
                                                       const digest_type& description_digest,
                                                       flat_set<digest_type>&& dependencies,
                                                       const protocol_feature_subjective_restrictions& restrictions )
   :protocol_feature_base( protocol_feature_t::builtin, description_digest, std::move(dependencies), restrictions )
   ,_codename(codename)
   {
      auto itr = builtin_protocol_feature_codenames.find( codename );
      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t passed to constructor: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      builtin_feature_codename = itr->second.codename;
   }

   void builtin_protocol_feature::reflector_init() {
      protocol_feature_base::reflector_init();

      for( const auto& p : builtin_protocol_feature_codenames ) {
         if( builtin_feature_codename.compare( p.second.codename ) == 0 ) {
            _codename = p.first;
            return;
         }
      }

      EOS_THROW( protocol_feature_validation_exception,
                 "Unsupported builtin protocol feature codename: ${codename}",
                 ("codename", builtin_feature_codename) );
   }

   digest_type builtin_protocol_feature::digest()const {
      digest_type::encoder enc;
      fc::raw::pack( enc, _type );
      fc::raw::pack( enc, description_digest  );
      fc::raw::pack( enc, dependencies );
      fc::raw::pack( enc, _codename );

      return enc.result();
   }

   protocol_feature_manager::protocol_feature_manager() {
      _builtin_protocol_features.reserve( builtin_protocol_feature_codenames.size() );
   }

   protocol_feature_manager::recognized_t
   protocol_feature_manager::is_recognized( const digest_type& feature_digest, time_point now )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      if( itr == _recognized_protocol_features.end() )
         return recognized_t::unrecognized;

      if( !itr->enabled )
         return recognized_t::disabled;

      if( itr->earliest_allowed_activation_time > now )
         return recognized_t::too_early;

      if( itr->preactivation_required )
         return recognized_t::ready_if_preactivated;

      return recognized_t::ready;
   }

   const protocol_feature_manager::protocol_feature&
   protocol_feature_manager::get_protocol_feature( const digest_type& feature_digest )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
                  "unrecognized protocol feature with digest: ${digest}",
                  ("digest", feature_digest)
      );

      return *itr;
   }

   bool protocol_feature_manager::is_builtin_activated( builtin_protocol_feature_t feature_codename,
                                                        uint32_t current_block_num )const
   {
      uint32_t indx = static_cast<uint32_t>( feature_codename );

      if( indx >= _builtin_protocol_features.size() ) return false;

      return (_builtin_protocol_features[indx].activation_block_num <= current_block_num);
   }

   optional<digest_type>
   protocol_feature_manager::get_builtin_digest( builtin_protocol_feature_t feature_codename )const
   {
      uint32_t indx = static_cast<uint32_t>( feature_codename );

      if( indx >= _builtin_protocol_features.size() )
         return {};

      if( _builtin_protocol_features[indx].iterator_to_protocol_feature == _recognized_protocol_features.end() )
         return {};

      return _builtin_protocol_features[indx].iterator_to_protocol_feature->feature_digest;
   }

   bool protocol_feature_manager::validate_dependencies(
                                    const digest_type& feature_digest,
                                    const std::function<bool(const digest_type&)>& validator
   )const {
      auto itr = _recognized_protocol_features.find( feature_digest );

      if( itr == _recognized_protocol_features.end() ) return false;

      for( const auto& d : itr->dependencies ) {
         if( !validator(d) ) return false;
      }

      return true;
   }

   builtin_protocol_feature
   protocol_feature_manager::make_default_builtin_protocol_feature(
      builtin_protocol_feature_t codename,
      const std::function<void(builtin_protocol_feature_t dependency)>& handle_dependency
   )const {
      auto itr = builtin_protocol_feature_codenames.find( codename );

      EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Unsupported builtin_protocol_feature_t: ${codename}",
                  ("codename", static_cast<uint32_t>(codename)) );

      flat_set<digest_type> dependencies;
      dependencies.reserve( itr->second.builtin_dependencies.size() );

      for( const auto& d : itr->second.builtin_dependencies ) {
         handle_dependency( d );
         auto dependency_digest = get_builtin_digest( d );
         EOS_ASSERT( dependency_digest, protocol_feature_exception,
                     "cannot make default builtin protocol feature with codename '${codename}' since it has a dependency that has not been added yet: ${dependency_codename}",
                     ("codename", static_cast<uint32_t>(itr->first))
                     ("dependency_codename", static_cast<uint32_t>(d))
         );
         dependencies.insert( *dependency_digest );
      }

      return {itr->first, itr->second.description_digest, std::move(dependencies), itr->second.subjective_restrictions};
   }

   void protocol_feature_manager::add_feature( const builtin_protocol_feature& f ) {
      EOS_ASSERT( _head_of_builtin_activation_list == builtin_protocol_feature_entry::no_previous,
                  protocol_feature_exception,
                  "new builtin protocol features cannot be added after a protocol feature has already been activated" );

      auto builtin_itr = builtin_protocol_feature_codenames.find( f._codename );
      EOS_ASSERT( builtin_itr != builtin_protocol_feature_codenames.end(), protocol_feature_validation_exception,
                  "Builtin protocol feature has unsupported builtin_protocol_feature_t: ${codename}",
                  ("codename", static_cast<uint32_t>( f._codename )) );

      uint32_t indx = static_cast<uint32_t>( f._codename );

      if( indx < _builtin_protocol_features.size() ) {
         EOS_ASSERT( _builtin_protocol_features[indx].iterator_to_protocol_feature == _recognized_protocol_features.end(),
                     protocol_feature_exception,
                     "builtin protocol feature with codename '${codename}' already added",
                     ("codename", f.builtin_feature_codename) );
      }

      auto feature_digest = f.digest();

      const auto& expected_builtin_dependencies = builtin_itr->second.builtin_dependencies;
      flat_set<builtin_protocol_feature_t> satisfied_builtin_dependencies;
      satisfied_builtin_dependencies.reserve( expected_builtin_dependencies.size() );

      for( const auto& d : f.dependencies ) {
         auto itr = _recognized_protocol_features.find( d );
         EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
            "builtin protocol feature with codename '${codename}' and digest of ${digest} has a dependency on a protocol feature with digest ${dependency_digest} that is not recognized",
            ("codename", f.builtin_feature_codename)
            ("digest",  feature_digest)
            ("dependency_digest", d )
         );

         if( itr->builtin_feature
             && expected_builtin_dependencies.find( *itr->builtin_feature )
                  != expected_builtin_dependencies.end() )
         {
            satisfied_builtin_dependencies.insert( *itr->builtin_feature );
         }
      }

      if( expected_builtin_dependencies.size() > satisfied_builtin_dependencies.size() ) {
         flat_set<builtin_protocol_feature_t> missing_builtins;
         missing_builtins.reserve( expected_builtin_dependencies.size() - satisfied_builtin_dependencies.size() );
         std::set_difference( expected_builtin_dependencies.begin(), expected_builtin_dependencies.end(),
                              satisfied_builtin_dependencies.begin(), satisfied_builtin_dependencies.end(),
                              end_inserter( missing_builtins )
         );

         vector<string> missing_builtins_with_names;
         missing_builtins_with_names.reserve( missing_builtins.size() );
         for( const auto& builtin_codename : missing_builtins ) {
            auto itr = builtin_protocol_feature_codenames.find( builtin_codename );
            EOS_ASSERT( itr != builtin_protocol_feature_codenames.end(),
                        protocol_feature_exception,
                        "Unexpected error"
            );
            missing_builtins_with_names.emplace_back( itr->second.codename );
         }

         EOS_THROW(  protocol_feature_validation_exception,
                     "Not all the builtin dependencies of the builtin protocol feature with codename '${codename}' and digest of ${digest} were satisfied.",
                     ("missing_dependencies", missing_builtins_with_names)
         );
      }

      auto res = _recognized_protocol_features.insert( protocol_feature{
         feature_digest,
         f.dependencies,
         f.subjective_restrictions.earliest_allowed_activation_time,
         f.subjective_restrictions.preactivation_required,
         f.subjective_restrictions.enabled,
         f._codename
      } );

      EOS_ASSERT( res.second, protocol_feature_exception,
                  "builtin protocol feature with codename '${codename}' has a digest of ${digest} but another protocol feature with the same digest has already been added",
                  ("codename", f.builtin_feature_codename)("digest", feature_digest) );

      if( indx < _builtin_protocol_features.size() ) {
         for( auto i =_builtin_protocol_features.size(); i <= indx; ++i ) {
            _builtin_protocol_features.push_back( builtin_protocol_feature_entry{
                                                   _recognized_protocol_features.end(),
                                                   builtin_protocol_feature_entry::not_active
                                                  } );
         }
      }

      _builtin_protocol_features[indx].iterator_to_protocol_feature = res.first;
   }

   void protocol_feature_manager::activate_feature( const digest_type& feature_digest,
                                                    uint32_t current_block_num )
   {
      auto itr = _recognized_protocol_features.find( feature_digest );

      EOS_ASSERT( itr != _recognized_protocol_features.end(), protocol_feature_exception,
                  "unrecognized protocol feature digest: ${digest}", ("digest", feature_digest) );

      if( itr->builtin_feature ) {
         if( _head_of_builtin_activation_list != builtin_protocol_feature_entry::no_previous ) {
            auto largest_block_num_of_activated_builtins = _builtin_protocol_features[_head_of_builtin_activation_list].activation_block_num;
            EOS_ASSERT( largest_block_num_of_activated_builtins <= current_block_num,
                        protocol_feature_exception,
                        "trying to activate a builtin protocol feature with a current block number of "
                        "${current_block_num} when the largest activation block number of all activated builtin "
                        "protocol features is ${largest_block_num_of_activated_builtins}",
                        ("current_block_num", current_block_num)
                        ("largest_block_num_of_activated_builtins", largest_block_num_of_activated_builtins)
            );
         }

         uint32_t indx = static_cast<uint32_t>( *itr->builtin_feature );

         EOS_ASSERT( indx < _builtin_protocol_features.size() &&
                     _builtin_protocol_features[indx].iterator_to_protocol_feature != _recognized_protocol_features.end(),
                     protocol_feature_exception,
                     "invariant failure: problem with activating builtin protocol feature with digest: ${digest}",
                     ("digest", feature_digest) );

         EOS_ASSERT( _builtin_protocol_features[indx].activation_block_num == builtin_protocol_feature_entry::not_active,
                     protocol_feature_exception,
                     "cannot activate already activated builtin feature with digest: ${digest}",
                     ("digest", feature_digest) );

         _builtin_protocol_features[indx].activation_block_num = current_block_num;
         _builtin_protocol_features[indx].previous = _head_of_builtin_activation_list;
         _head_of_builtin_activation_list = indx;
      }
   }

   void protocol_feature_manager::popped_blocks_to( uint32_t block_num ) {
      while( _head_of_builtin_activation_list != builtin_protocol_feature_entry::no_previous ) {
         auto& e = _builtin_protocol_features[_head_of_builtin_activation_list];
         if( e.activation_block_num <= block_num ) break;

         _head_of_builtin_activation_list = e.previous;
         e.activation_block_num = builtin_protocol_feature_entry::not_active;
         e.previous = builtin_protocol_feature_entry::no_previous;
      }
   }

} }  // eosio::chain
<|endoftext|>


<commit_before>//
//  array.cpp
//  DS
//
//  Created by Rahul Goel on 7/26/17.
//  Copyright © 2017 Rahul Goel. All rights reserved.
//

#include "array.hpp"

void array_rotateLeftBydElements(int arr[],int size,int d){

}

void array_rotateCyclicallyby1(int arr[],int size){
    //To store last element seprately
    int last = arr[size -1];
    int f = arr[0];

    //Shift all the elements one position right
    int i = 1;
    while (i<size) {
        f = arr[i];
        arr[i] = f;
        i++;
    }

    //Put the last element in first position
    arr[0] = last;

    //Print the modified array
    array_printelements(arr, size);
}

void array_searchInSortedAndRotatedarray(int arr[],int size, int d){

}

void array_printelements(int arr[], int size){
    int i =0;
    printf("Array is : \n");
    while (i<size) {
        printf("%d ",arr[i]);
        i++;
    }
    printf("\n");
}
<commit_msg>array_missingnumber<commit_after>//
//  array.cpp
//  DS
//
//  Created by Rahul Goel on 7/26/17.
//  Copyright © 2017 Rahul Goel. All rights reserved.
//

#include "array.hpp"

void array_rotateLeftBydElements(int arr[],int size,int d){

}

void array_rotateCyclicallyby1(int arr[],int size){
    //To store last element seprately
    int last = arr[size -1];
    int f = arr[0];

    //Shift all the elements one position right
    int i = 1;
    while (i<size) {
        f = arr[i];
        arr[i] = f;
        i++;
    }

    //Put the last element in first position
    arr[0] = last;

    //Print the modified array
    array_printelements(arr, size);
}

void array_searchInSortedAndRotatedarray(int arr[],int size, int d){

}

void array_printelements(int arr[], int size){
    int i =0;
    printf("Array is : \n");
    while (i<size) {
        printf("%d ",arr[i]);
        i++;
    }
    printf("\n");
}

int array_missingnumber(int arr[], int n){

    //Sum of numbers from 1 to n
    int total = n*(n - 1)/2;

    //sum of all the array elements
    int sum = 0;
    int i = 0;

    while (i<sum) {
        sum = sum + arr[i];
        i++;
    }

    int missingNumber = total - sum ;
    return missingNumber;
}
<|endoftext|>


<commit_before>#include "mbed.h"
#include "test_env.h"
#include "rtos.h"

#if defined(MBED_RTOS_SINGLE_THREAD)
  #error [NOT_SUPPORTED] test not supported
#endif

#define THREAD_DELAY     75
#define SEMAPHORE_SLOTS  2
#define SEM_CHANGES      100

/*
 * The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
 * the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
 * and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
 */
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
    #define STACK_SIZE DEFAULT_STACK_SIZE/16
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
    #define STACK_SIZE DEFAULT_STACK_SIZE/8
#elif defined(TARGET_STM32F334R8) && (defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_IAR))
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F103RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_EFM32HG_STK3400)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 512
#elif (defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32PG_STK3401)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 768
#elif (defined(TARGET_EFM32GG_STK3700)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 1536
#elif defined(TARGET_MCU_NRF51822)
    #define STACK_SIZE 512
#else
    #define STACK_SIZE DEFAULT_STACK_SIZE
#endif

void print_char(char c = '*') {
    printf("%c", c);
    fflush(stdout);
}

Semaphore two_slots(SEMAPHORE_SLOTS);

volatile int change_counter = 0;
volatile int sem_counter = 0;
volatile bool sem_defect = false;

void test_thread(void const *delay) {
    const int thread_delay = int(delay);
    while (true) {
        two_slots.wait();
        sem_counter++;
        const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS;
        const char msg = sem_lock_failed ? 'e' : sem_counter + '0';
        print_char(msg);
        if (sem_lock_failed) {
            sem_defect = true;
        }
        Thread::wait(thread_delay);
        print_char('.');
        sem_counter--;
        change_counter++;
        two_slots.release();
    }
}

int main (void) {
    MBED_HOSTTEST_TIMEOUT(20);
    MBED_HOSTTEST_SELECT(default_auto);
    MBED_HOSTTEST_DESCRIPTION(Semaphore resource lock);
    MBED_HOSTTEST_START("RTOS_3");

    const int t1_delay = THREAD_DELAY * 1;
    const int t2_delay = THREAD_DELAY * 2;
    const int t3_delay = THREAD_DELAY * 3;
    Thread t1(test_thread, (void *)t1_delay, osPriorityNormal, STACK_SIZE);
    Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
    Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);

    while (true) {
        if (change_counter >= SEM_CHANGES or sem_defect == true) {
            t1.terminate();
            t2.terminate();
            t3.terminate();
            break;
        }
    }

    fflush(stdout);
    MBED_HOSTTEST_RESULT(!sem_defect);
    return 0;
}
<commit_msg>Revert "Decrease nrf51 semaphore test stack size"<commit_after>#include "mbed.h"
#include "test_env.h"
#include "rtos.h"

#if defined(MBED_RTOS_SINGLE_THREAD)
  #error [NOT_SUPPORTED] test not supported
#endif

#define THREAD_DELAY     75
#define SEMAPHORE_SLOTS  2
#define SEM_CHANGES      100

/*
 * The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
 * the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
 * and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
 */
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
    #define STACK_SIZE DEFAULT_STACK_SIZE/16
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
    #define STACK_SIZE DEFAULT_STACK_SIZE/8
#elif defined(TARGET_STM32F334R8) && (defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_IAR))
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F103RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/2
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
    #define STACK_SIZE DEFAULT_STACK_SIZE/4
#elif (defined(TARGET_EFM32HG_STK3400)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 512
#elif (defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32PG_STK3401)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 768
#elif (defined(TARGET_EFM32GG_STK3700)) && !defined(TOOLCHAIN_ARM_MICRO)
    #define STACK_SIZE 1536
#elif defined(TARGET_MCU_NRF51822)
    #define STACK_SIZE 768
#else
    #define STACK_SIZE DEFAULT_STACK_SIZE
#endif

void print_char(char c = '*') {
    printf("%c", c);
    fflush(stdout);
}

Semaphore two_slots(SEMAPHORE_SLOTS);

volatile int change_counter = 0;
volatile int sem_counter = 0;
volatile bool sem_defect = false;

void test_thread(void const *delay) {
    const int thread_delay = int(delay);
    while (true) {
        two_slots.wait();
        sem_counter++;
        const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS;
        const char msg = sem_lock_failed ? 'e' : sem_counter + '0';
        print_char(msg);
        if (sem_lock_failed) {
            sem_defect = true;
        }
        Thread::wait(thread_delay);
        print_char('.');
        sem_counter--;
        change_counter++;
        two_slots.release();
    }
}

int main (void) {
    MBED_HOSTTEST_TIMEOUT(20);
    MBED_HOSTTEST_SELECT(default_auto);
    MBED_HOSTTEST_DESCRIPTION(Semaphore resource lock);
    MBED_HOSTTEST_START("RTOS_3");

    const int t1_delay = THREAD_DELAY * 1;
    const int t2_delay = THREAD_DELAY * 2;
    const int t3_delay = THREAD_DELAY * 3;
    Thread t1(test_thread, (void *)t1_delay, osPriorityNormal, STACK_SIZE);
    Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
    Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);

    while (true) {
        if (change_counter >= SEM_CHANGES or sem_defect == true) {
            t1.terminate();
            t2.terminate();
            t3.terminate();
            break;
        }
    }

    fflush(stdout);
    MBED_HOSTTEST_RESULT(!sem_defect);
    return 0;
}
<|endoftext|>


<commit_before>#include "LedDeviceAPA104.h"

/*
From the data sheet:

(TH+TL=1.25μs±600ns)

T0H,	 0 code, high level time,	  350ns ±150ns
T0L,	 0 code, low level time,	 1360ns ±150ns
T1H,	 1 code, high level time,	  360ns ±150ns
T1L,	 1 code, low level time,	   45ns ±150ns
WT,	 Wait for the processing time,	 NA
Trst,	 Reset code,low level time,	 24µs

To normalise the pulse times so they fit in 4 SPI bits:

On the assumption that the "low" time doesnt matter much

A SPI bit time of 0.40uS = 2.5 Mbit/sec
T0 is sent as 1000
T1 is sent as 1110

With a bit of excel testing, we can work out the maximum and minimum speeds:
2000000 MIN
2235000 AVG
2470000 MAX

Wait time:
Not Applicable for WS2812

Reset time:
using the max of 2470000, the bit time is 405nS
Reset time is 24uS = 59 bits = 8 bytes

*/

LedDeviceAPA104::LedDeviceAPA104(const QJsonObject &deviceConfig)
	: ProviderSpi()
	, SPI_BYTES_PER_COLOUR(4)
	, SPI_FRAME_END_LATCH_BYTES(116)
	, bitpair_to_byte {
		0b10001000,
		0b10001100,
		0b11001000,
		0b11001100,
	}
{
	_deviceReady = init(deviceConfig);
}

LedDevice* LedDeviceAPA104::construct(const QJsonObject &deviceConfig)
{
	return new LedDeviceAPA104(deviceConfig);
}

bool LedDeviceAPA104::init(const QJsonObject &deviceConfig)
{
	_baudRate_Hz = 2235000;
	if ( !ProviderSpi::init(deviceConfig) )
	{
		return false;
	}
	WarningIf(( _baudRate_Hz < 2000000 || _baudRate_Hz > 2470000 ), _log, "SPI rate %d outside recommended range (2000000 -> 2470000)", _baudRate_Hz);

	_ledBuffer.resize(_ledRGBCount * SPI_BYTES_PER_COLOUR + SPI_FRAME_END_LATCH_BYTES, 0x00);

	return true;
}

int LedDeviceAPA104::write(const std::vector<ColorRgb> &ledValues)
{
	unsigned spi_ptr = 0;
	const int SPI_BYTES_PER_LED = sizeof(ColorRgb) * SPI_BYTES_PER_COLOUR;

	for (const ColorRgb& color : ledValues)
	{
		uint32_t colorBits = ((unsigned int)color.red << 16)
			| ((unsigned int)color.green << 8)
			| color.blue;

		for (int j=SPI_BYTES_PER_LED - 1; j>=0; j--)
		{
			_ledBuffer[spi_ptr+j] = bitpair_to_byte[ colorBits & 0x3 ];
			colorBits >>= 2;
		}
		spi_ptr += SPI_BYTES_PER_LED;
	}

	for (int j=0; j < SPI_FRAME_END_LATCH_BYTES; j++)
	{
		_ledBuffer[spi_ptr++] = 0;
	}

	return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}
<commit_msg>fixed bitpair_to_byte table fixed end frame byte count<commit_after>#include "LedDeviceAPA104.h"

/*
From the data sheet:

(TH+TL=1.25μs±600ns)

T0H,	 0 code, high level time,	  350ns ±150ns
T0L,	 0 code, low level time,	 1360ns ±150ns
T1H,	 1 code, high level time,	  360ns ±150ns
T1L,	 1 code, low level time,	   45ns ±150ns
WT,	 Wait for the processing time,	 NA
Trst,	 Reset code,low level time,	 24µs

To normalise the pulse times so they fit in 4 SPI bits:

On the assumption that the "low" time doesnt matter much

A SPI bit time of 0.40uS = 2.5 Mbit/sec
T0 is sent as 1000
T1 is sent as 1110

With a bit of excel testing, we can work out the maximum and minimum speeds:
2000000 MIN
2235000 AVG
2470000 MAX

Wait time:
Not Applicable for WS2812

Reset time:
using the max of 2470000, the bit time is 405nS
Reset time is 24uS = 59 bits = 8 bytes

*/

LedDeviceAPA104::LedDeviceAPA104(const QJsonObject &deviceConfig)
	: ProviderSpi()
	, SPI_BYTES_PER_COLOUR(4)
	, SPI_FRAME_END_LATCH_BYTES(8)
	, bitpair_to_byte {
		0b10001000,
		0b10001110,
		0b11101000,
		0b11101110,
	}
{
	_deviceReady = init(deviceConfig);
}

LedDevice* LedDeviceAPA104::construct(const QJsonObject &deviceConfig)
{
	return new LedDeviceAPA104(deviceConfig);
}

bool LedDeviceAPA104::init(const QJsonObject &deviceConfig)
{
	_baudRate_Hz = 2235000;
	if ( !ProviderSpi::init(deviceConfig) )
	{
		return false;
	}
	WarningIf(( _baudRate_Hz < 2000000 || _baudRate_Hz > 2470000 ), _log, "SPI rate %d outside recommended range (2000000 -> 2470000)", _baudRate_Hz);

	_ledBuffer.resize(_ledRGBCount * SPI_BYTES_PER_COLOUR + SPI_FRAME_END_LATCH_BYTES, 0x00);

	return true;
}

int LedDeviceAPA104::write(const std::vector<ColorRgb> &ledValues)
{
	unsigned spi_ptr = 0;
	const int SPI_BYTES_PER_LED = sizeof(ColorRgb) * SPI_BYTES_PER_COLOUR;

	for (const ColorRgb& color : ledValues)
	{
		uint32_t colorBits = ((unsigned int)color.red << 16)
			| ((unsigned int)color.green << 8)
			| color.blue;

		for (int j=SPI_BYTES_PER_LED - 1; j>=0; j--)
		{
			_ledBuffer[spi_ptr+j] = bitpair_to_byte[ colorBits & 0x3 ];
			colorBits >>= 2;
		}
		spi_ptr += SPI_BYTES_PER_LED;
	}

	for (int j=0; j < SPI_FRAME_END_LATCH_BYTES; j++)
	{
		_ledBuffer[spi_ptr++] = 0;
	}

	return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/web_contents_preferences.h"

#include <algorithm>
#include <string>
#include <vector>

#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
#include "native_mate/dictionary.h"
#include "net/base/filename_util.h"
#include "cc/base/switches.h"

#if defined(OS_WIN)
#include "ui/gfx/switches.h"
#endif

DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);

namespace atom {

// static
std::vector<WebContentsPreferences*> WebContentsPreferences::instances_;

WebContentsPreferences::WebContentsPreferences(
    content::WebContents* web_contents,
    const mate::Dictionary& web_preferences)
    : web_contents_(web_contents) {
  v8::Isolate* isolate = web_preferences.isolate();
  mate::Dictionary copied(isolate, web_preferences.GetHandle()->Clone());
  // Following fields should not be stored.
  copied.Delete("embedder");
  copied.Delete("isGuest");
  copied.Delete("session");

  mate::ConvertFromV8(isolate, copied.GetHandle(), &web_preferences_);
  web_contents->SetUserData(UserDataKey(), this);

  instances_.push_back(this);
}

WebContentsPreferences::~WebContentsPreferences() {
  instances_.erase(
      std::remove(instances_.begin(), instances_.end(), this),
      instances_.end());
}

void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
  web_preferences_.MergeDictionary(&extend);
}

// static
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
    int process_id) {
  for (WebContentsPreferences* preferences : instances_) {
    content::WebContents* web_contents = preferences->web_contents_;
    if (web_contents->GetRenderProcessHost()->GetID() == process_id)
      return web_contents;
  }
  return nullptr;
}

// static
void WebContentsPreferences::AppendExtraCommandLineSwitches(
    content::WebContents* web_contents, base::CommandLine* command_line) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  base::DictionaryValue& web_preferences = self->web_preferences_;

  bool b;
  // Check if plugins are enabled.
  if (web_preferences.GetBoolean("plugins", &b) && b)
    command_line->AppendSwitch(switches::kEnablePlugins);

  // Experimental flags.
  if (web_preferences.GetBoolean(options::kExperimentalFeatures, &b) && b)
    command_line->AppendSwitch(
        ::switches::kEnableExperimentalWebPlatformFeatures);
  if (web_preferences.GetBoolean(options::kExperimentalCanvasFeatures, &b) && b)
    command_line->AppendSwitch(::switches::kEnableExperimentalCanvasFeatures);

  // Check if we have node integration specified.
  bool node_integration = true;
  web_preferences.GetBoolean(options::kNodeIntegration, &node_integration);
  command_line->AppendSwitchASCII(switches::kNodeIntegration,
                                  node_integration ? "true" : "false");

  // The preload script.
  base::FilePath::StringType preload;
  if (web_preferences.GetString(options::kPreloadScript, &preload)) {
    if (base::FilePath(preload).IsAbsolute())
      command_line->AppendSwitchNative(switches::kPreloadScript, preload);
    else
      LOG(ERROR) << "preload script must have absolute path.";
  } else if (web_preferences.GetString(options::kPreloadURL, &preload)) {
    // Translate to file path if there is "preload-url" option.
    base::FilePath preload_path;
    if (net::FileURLToFilePath(GURL(preload), &preload_path))
      command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
    else
      LOG(ERROR) << "preload url must be file:// protocol.";
  }

  // --background-color.
  std::string color;
  if (web_preferences.GetString(options::kBackgroundColor, &color))
    command_line->AppendSwitchASCII(switches::kBackgroundColor, color);

  // The zoom factor.
  double zoom_factor = 1.0;
  if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) &&
      zoom_factor != 1.0)
    command_line->AppendSwitchASCII(switches::kZoomFactor,
                                    base::DoubleToString(zoom_factor));

  // --guest-instance-id, which is used to identify guest WebContents.
  int guest_instance_id = 0;
  if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
    command_line->AppendSwitchASCII(switches::kGuestInstanceID,
                                    base::IntToString(guest_instance_id));

  // Pass the opener's window id.
  int opener_id;
  if (web_preferences.GetInteger(options::kOpenerID, &opener_id))
    command_line->AppendSwitchASCII(switches::kOpenerID,
                                    base::IntToString(opener_id));

#if defined(OS_MACOSX)
  // Enable scroll bounce.
  bool scroll_bounce;
  if (web_preferences.GetBoolean(options::kScrollBounce, &scroll_bounce) &&
      scroll_bounce)
    command_line->AppendSwitch(switches::kScrollBounce);
#endif

  // Custom command line switches.
  const base::ListValue* args;
  if (web_preferences.GetList("commandLineSwitches", &args)) {
    for (size_t i = 0; i < args->GetSize(); ++i) {
      std::string arg;
      if (args->GetString(i, &arg) && !arg.empty())
        command_line->AppendSwitch(arg);
    }
  }

  // Enable blink features.
  std::string blink_features;
  if (web_preferences.GetString(options::kBlinkFeatures, &blink_features))
    command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures,
                                    blink_features);

  // Disable blink features.
  std::string disable_blink_features;
  if (web_preferences.GetString(options::kDisableBlinkFeatures,
                                &disable_blink_features))
    command_line->AppendSwitchASCII(::switches::kDisableBlinkFeatures,
                                    disable_blink_features);

  // The initial visibility state.
  NativeWindow* window = NativeWindow::FromWebContents(web_contents);

  // Use embedder window for webviews
  if (guest_instance_id && !window) {
    auto manager = WebViewManager::GetWebViewManager(web_contents);
    if (manager) {
      auto embedder = manager->GetEmbedder(guest_instance_id);
      if (embedder)
        window = NativeWindow::FromWebContents(embedder);
    }
  }

  if (window) {
    bool visible = window->IsVisible() && !window->IsMinimized();
    if (!visible)  // Default state is visible.
      command_line->AppendSwitch("hidden-page");
  }

  command_line->AppendSwitch(cc::switches::kEnableBeginFrameScheduling);
  command_line->AppendSwitch(cc::switches::kShowFPSCounter);
}

// static
void WebContentsPreferences::OverrideWebkitPrefs(
    content::WebContents* web_contents, content::WebPreferences* prefs) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  bool b;
  if (self->web_preferences_.GetBoolean("javascript", &b))
    prefs->javascript_enabled = b;
  if (self->web_preferences_.GetBoolean("images", &b))
    prefs->images_enabled = b;
  if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b))
    prefs->text_areas_are_resizable = b;
  if (self->web_preferences_.GetBoolean("webgl", &b))
    prefs->experimental_webgl_enabled = b;
  if (self->web_preferences_.GetBoolean("webSecurity", &b)) {
    prefs->web_security_enabled = b;
    prefs->allow_displaying_insecure_content = !b;
    prefs->allow_running_insecure_content = !b;
  }
  if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b))
    prefs->allow_displaying_insecure_content = b;
  if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b))
    prefs->allow_running_insecure_content = b;
  const base::DictionaryValue* fonts = nullptr;
  if (self->web_preferences_.GetDictionary("defaultFontFamily", &fonts)) {
    base::string16 font;
    if (fonts->GetString("standard", &font))
      prefs->standard_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("serif", &font))
      prefs->serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("sansSerif", &font))
      prefs->sans_serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("monospace", &font))
      prefs->fixed_font_family_map[content::kCommonScript] = font;
  }
  int size;
  if (self->web_preferences_.GetInteger("defaultFontSize", &size))
    prefs->default_font_size = size;
  if (self->web_preferences_.GetInteger("defaultMonospaceFontSize", &size))
    prefs->default_fixed_font_size = size;
  if (self->web_preferences_.GetInteger("minimumFontSize", &size))
    prefs->minimum_font_size = size;
  std::string encoding;
  if (self->web_preferences_.GetString("defaultEncoding", &encoding))
    prefs->default_encoding = encoding;
}

}  // namespace atom
<commit_msg>remove fpscounter, can be enabled from node<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/web_contents_preferences.h"

#include <algorithm>
#include <string>
#include <vector>

#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
#include "native_mate/dictionary.h"
#include "net/base/filename_util.h"
#include "cc/base/switches.h"

#if defined(OS_WIN)
#include "ui/gfx/switches.h"
#endif

DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);

namespace atom {

// static
std::vector<WebContentsPreferences*> WebContentsPreferences::instances_;

WebContentsPreferences::WebContentsPreferences(
    content::WebContents* web_contents,
    const mate::Dictionary& web_preferences)
    : web_contents_(web_contents) {
  v8::Isolate* isolate = web_preferences.isolate();
  mate::Dictionary copied(isolate, web_preferences.GetHandle()->Clone());
  // Following fields should not be stored.
  copied.Delete("embedder");
  copied.Delete("isGuest");
  copied.Delete("session");

  mate::ConvertFromV8(isolate, copied.GetHandle(), &web_preferences_);
  web_contents->SetUserData(UserDataKey(), this);

  instances_.push_back(this);
}

WebContentsPreferences::~WebContentsPreferences() {
  instances_.erase(
      std::remove(instances_.begin(), instances_.end(), this),
      instances_.end());
}

void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
  web_preferences_.MergeDictionary(&extend);
}

// static
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
    int process_id) {
  for (WebContentsPreferences* preferences : instances_) {
    content::WebContents* web_contents = preferences->web_contents_;
    if (web_contents->GetRenderProcessHost()->GetID() == process_id)
      return web_contents;
  }
  return nullptr;
}

// static
void WebContentsPreferences::AppendExtraCommandLineSwitches(
    content::WebContents* web_contents, base::CommandLine* command_line) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  base::DictionaryValue& web_preferences = self->web_preferences_;

  bool b;
  // Check if plugins are enabled.
  if (web_preferences.GetBoolean("plugins", &b) && b)
    command_line->AppendSwitch(switches::kEnablePlugins);

  // Experimental flags.
  if (web_preferences.GetBoolean(options::kExperimentalFeatures, &b) && b)
    command_line->AppendSwitch(
        ::switches::kEnableExperimentalWebPlatformFeatures);
  if (web_preferences.GetBoolean(options::kExperimentalCanvasFeatures, &b) && b)
    command_line->AppendSwitch(::switches::kEnableExperimentalCanvasFeatures);

  // Check if we have node integration specified.
  bool node_integration = true;
  web_preferences.GetBoolean(options::kNodeIntegration, &node_integration);
  command_line->AppendSwitchASCII(switches::kNodeIntegration,
                                  node_integration ? "true" : "false");

  // The preload script.
  base::FilePath::StringType preload;
  if (web_preferences.GetString(options::kPreloadScript, &preload)) {
    if (base::FilePath(preload).IsAbsolute())
      command_line->AppendSwitchNative(switches::kPreloadScript, preload);
    else
      LOG(ERROR) << "preload script must have absolute path.";
  } else if (web_preferences.GetString(options::kPreloadURL, &preload)) {
    // Translate to file path if there is "preload-url" option.
    base::FilePath preload_path;
    if (net::FileURLToFilePath(GURL(preload), &preload_path))
      command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
    else
      LOG(ERROR) << "preload url must be file:// protocol.";
  }

  // --background-color.
  std::string color;
  if (web_preferences.GetString(options::kBackgroundColor, &color))
    command_line->AppendSwitchASCII(switches::kBackgroundColor, color);

  // The zoom factor.
  double zoom_factor = 1.0;
  if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) &&
      zoom_factor != 1.0)
    command_line->AppendSwitchASCII(switches::kZoomFactor,
                                    base::DoubleToString(zoom_factor));

  // --guest-instance-id, which is used to identify guest WebContents.
  int guest_instance_id = 0;
  if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
    command_line->AppendSwitchASCII(switches::kGuestInstanceID,
                                    base::IntToString(guest_instance_id));

  // Pass the opener's window id.
  int opener_id;
  if (web_preferences.GetInteger(options::kOpenerID, &opener_id))
    command_line->AppendSwitchASCII(switches::kOpenerID,
                                    base::IntToString(opener_id));

#if defined(OS_MACOSX)
  // Enable scroll bounce.
  bool scroll_bounce;
  if (web_preferences.GetBoolean(options::kScrollBounce, &scroll_bounce) &&
      scroll_bounce)
    command_line->AppendSwitch(switches::kScrollBounce);
#endif

  // Custom command line switches.
  const base::ListValue* args;
  if (web_preferences.GetList("commandLineSwitches", &args)) {
    for (size_t i = 0; i < args->GetSize(); ++i) {
      std::string arg;
      if (args->GetString(i, &arg) && !arg.empty())
        command_line->AppendSwitch(arg);
    }
  }

  // Enable blink features.
  std::string blink_features;
  if (web_preferences.GetString(options::kBlinkFeatures, &blink_features))
    command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures,
                                    blink_features);

  // Disable blink features.
  std::string disable_blink_features;
  if (web_preferences.GetString(options::kDisableBlinkFeatures,
                                &disable_blink_features))
    command_line->AppendSwitchASCII(::switches::kDisableBlinkFeatures,
                                    disable_blink_features);

  // The initial visibility state.
  NativeWindow* window = NativeWindow::FromWebContents(web_contents);

  // Use embedder window for webviews
  if (guest_instance_id && !window) {
    auto manager = WebViewManager::GetWebViewManager(web_contents);
    if (manager) {
      auto embedder = manager->GetEmbedder(guest_instance_id);
      if (embedder)
        window = NativeWindow::FromWebContents(embedder);
    }
  }

  if (window) {
    bool visible = window->IsVisible() && !window->IsMinimized();
    if (!visible)  // Default state is visible.
      command_line->AppendSwitch("hidden-page");
  }

  command_line->AppendSwitch(cc::switches::kEnableBeginFrameScheduling);
}

// static
void WebContentsPreferences::OverrideWebkitPrefs(
    content::WebContents* web_contents, content::WebPreferences* prefs) {
  WebContentsPreferences* self = FromWebContents(web_contents);
  if (!self)
    return;

  bool b;
  if (self->web_preferences_.GetBoolean("javascript", &b))
    prefs->javascript_enabled = b;
  if (self->web_preferences_.GetBoolean("images", &b))
    prefs->images_enabled = b;
  if (self->web_preferences_.GetBoolean("textAreasAreResizable", &b))
    prefs->text_areas_are_resizable = b;
  if (self->web_preferences_.GetBoolean("webgl", &b))
    prefs->experimental_webgl_enabled = b;
  if (self->web_preferences_.GetBoolean("webSecurity", &b)) {
    prefs->web_security_enabled = b;
    prefs->allow_displaying_insecure_content = !b;
    prefs->allow_running_insecure_content = !b;
  }
  if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b))
    prefs->allow_displaying_insecure_content = b;
  if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b))
    prefs->allow_running_insecure_content = b;
  const base::DictionaryValue* fonts = nullptr;
  if (self->web_preferences_.GetDictionary("defaultFontFamily", &fonts)) {
    base::string16 font;
    if (fonts->GetString("standard", &font))
      prefs->standard_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("serif", &font))
      prefs->serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("sansSerif", &font))
      prefs->sans_serif_font_family_map[content::kCommonScript] = font;
    if (fonts->GetString("monospace", &font))
      prefs->fixed_font_family_map[content::kCommonScript] = font;
  }
  int size;
  if (self->web_preferences_.GetInteger("defaultFontSize", &size))
    prefs->default_font_size = size;
  if (self->web_preferences_.GetInteger("defaultMonospaceFontSize", &size))
    prefs->default_fixed_font_size = size;
  if (self->web_preferences_.GetInteger("minimumFontSize", &size))
    prefs->minimum_font_size = size;
  std::string encoding;
  if (self->web_preferences_.GetString("defaultEncoding", &encoding))
    prefs->default_encoding = encoding;
}

}  // namespace atom
<|endoftext|>