text:
using base::TimeDelta;
using base::TimeTicks;
using content::BrowserThread;
using content::WebContents;

namespace chromeos {

namespace {

// Name of the experiment to run.
const char kExperiment[] = "LowMemoryMargin";

#define EXPERIMENT_CUSTOM_COUNTS(name, sample, min, max, buckets)        \
    {                                                                    \
      UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, buckets);      \
      if (base::FieldTrialList::TrialExists(kExperiment))                \
        UMA_HISTOGRAM_CUSTOM_COUNTS(                                     \
            base::FieldTrial::MakeName(name, kExperiment),               \
            sample, min, max, buckets);                                  \
    }

// Record a size in megabytes, over a potential interval up to 32 GB.
#define EXPERIMENT_HISTOGRAM_MEGABYTES(name, sample)                     \
    EXPERIMENT_CUSTOM_COUNTS(name, sample, 1, 32768, 50)

// The default interval in seconds after which to adjust the oom_score_adj
// value.
const int kAdjustmentIntervalSeconds = 10;

// If there has been no priority adjustment in this interval, we assume the
// machine was suspended and correct our timing statistics.
const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4;

// The default interval in milliseconds to wait before setting the score of
// currently focused tab.
const int kFocusedTabScoreAdjustIntervalMs = 500;

// Returns a unique ID for a WebContents.  Do not cast back to a pointer, as
// the WebContents could be deleted if the user closed the tab.
int64 IdFromTabContents(WebContents* web_contents) {
  return reinterpret_cast<int64>(web_contents);
}

////////////////////////////////////////////////////////////////////////////////
// OomMemoryDetails logs details about all Chrome processes during an out-of-
// memory event in an attempt to identify the culprit, then discards a tab and
// deletes itself.
class OomMemoryDetails : public MemoryDetails {
 public:
  OomMemoryDetails();

  // MemoryDetails overrides:
  virtual void OnDetailsAvailable() OVERRIDE;

 private:
  virtual ~OomMemoryDetails() {}

  TimeTicks start_time_;

  DISALLOW_COPY_AND_ASSIGN(OomMemoryDetails);
};

OomMemoryDetails::OomMemoryDetails() {
  AddRef();  // Released in OnDetailsAvailable().
  start_time_ = TimeTicks::Now();
}

void OomMemoryDetails::OnDetailsAvailable() {
  TimeDelta delta = TimeTicks::Now() - start_time_;
  // These logs are collected by user feedback reports.  We want them to help
  // diagnose user-reported problems with frequently discarded tabs.
  LOG(WARNING) << "OOM details (" << delta.InMilliseconds() << " ms):\n"
      << ToLogString();
  if (g_browser_process && g_browser_process->oom_priority_manager())
    g_browser_process->oom_priority_manager()->DiscardTab();
  // Delete ourselves so we don't have to worry about OomPriorityManager
  // deleting us when we're still working.
  Release();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// OomPriorityManager

OomPriorityManager::TabStats::TabStats()
  : is_app(false),
    is_pinned(false),
    is_selected(false),
    is_discarded(false),
    renderer_handle(0),
    tab_contents_id(0) {
}

OomPriorityManager::TabStats::~TabStats() {
}

OomPriorityManager::OomPriorityManager()
    : focused_tab_pid_(0),
      discard_count_(0) {
  // We only need the low memory observer if we want to discard tabs.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDiscardTabs))
    low_memory_observer_.reset(new LowMemoryObserver);

  registrar_.Add(this,
      content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
      content::NotificationService::AllBrowserContextsAndSources());
  registrar_.Add(this,
      content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
      content::NotificationService::AllBrowserContextsAndSources());
  registrar_.Add(this,
      content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
      content::NotificationService::AllBrowserContextsAndSources());
}

OomPriorityManager::~OomPriorityManager() {
  Stop();
}

void OomPriorityManager::Start() {
  if (!timer_.IsRunning()) {
    timer_.Start(FROM_HERE,
                 TimeDelta::FromSeconds(kAdjustmentIntervalSeconds),
                 this,
                 &OomPriorityManager::AdjustOomPriorities);
  }
  if (low_memory_observer_.get())
    low_memory_observer_->Start();
  start_time_ = TimeTicks::Now();
}

void OomPriorityManager::Stop() {
  timer_.Stop();
  if (low_memory_observer_.get())
    low_memory_observer_->Stop();
}

std::vector<string16> OomPriorityManager::GetTabTitles() {
  TabStatsList stats = GetTabStatsOnUIThread();
  base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
  std::vector<string16> titles;
  titles.reserve(stats.size());
  TabStatsList::iterator it = stats.begin();
  for ( ; it != stats.end(); ++it) {
    string16 str;
    str.reserve(4096);
    str += it->title;
    str += ASCIIToUTF16(" (");
    int score = pid_to_oom_score_[it->renderer_handle];
    str += base::IntToString16(score);
    str += ASCIIToUTF16(")");
    str += ASCIIToUTF16(it->is_app ? " app" : "");
    str += ASCIIToUTF16(it->is_pinned ? " pinned" : "");
    str += ASCIIToUTF16(it->is_discarded ? " discarded" : "");
    titles.push_back(str);
  }
  return titles;
}

// TODO(jamescook): This should consider tabs with references to other tabs,
// such as tabs created with JavaScript window.open().  We might want to
// discard the entire set together, or use that in the priority computation.
bool OomPriorityManager::DiscardTab() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  TabStatsList stats = GetTabStatsOnUIThread();
  if (stats.empty())
    return false;
  // Loop until we find a non-discarded tab to kill.
  for (TabStatsList::const_reverse_iterator stats_rit = stats.rbegin();
       stats_rit != stats.rend();
       ++stats_rit) {
    int64 least_important_tab_id = stats_rit->tab_contents_id;
    if (DiscardTabById(least_important_tab_id))
      return true;
  }
  return false;
}

void OomPriorityManager::LogMemoryAndDiscardTab() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // Deletes itself upon completion.
  OomMemoryDetails* details = new OomMemoryDetails();
  details->StartFetch(MemoryDetails::SKIP_USER_METRICS);
}

bool OomPriorityManager::DiscardTabById(int64 target_web_contents_id) {
  for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
       browser_iterator != BrowserList::end(); ++browser_iterator) {
    Browser* browser = *browser_iterator;
    TabStripModel* model = browser->tab_strip_model();
    for (int idx = 0; idx < model->count(); idx++) {
      // Can't discard tabs that are already discarded or active.
      if (model->IsTabDiscarded(idx) || (model->active_index() == idx))
        continue;
      WebContents* web_contents = model->GetTabContentsAt(idx)->web_contents();
      int64 web_contents_id = IdFromTabContents(web_contents);
      if (web_contents_id == target_web_contents_id) {
        LOG(WARNING) << "Discarding tab " << idx
            << " id " << target_web_contents_id;
        // Record statistics before discarding because we want to capture the
        // memory state that lead to the discard.
        RecordDiscardStatistics();
        model->DiscardTabContentsAt(idx);
        return true;
      }
    }
  }
  return false;
}

void OomPriorityManager::RecordDiscardStatistics() {
  // Record a raw count so we can compare to discard reloads.
  discard_count_++;
  EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.DiscardCount",
                           discard_count_, 1, 1000, 50);

  // TODO(jamescook): Maybe incorporate extension count?
  EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.TabCount", GetTabCount(), 1, 100, 50);

  // TODO(jamescook): If the time stats prove too noisy, then divide up users
  // based on how heavily they use Chrome using tab count as a proxy.
  // Bin into <= 1, <= 2, <= 4, <= 8, etc.
  if (last_discard_time_.is_null()) {
    // This is the first discard this session.
    TimeDelta interval = TimeTicks::Now() - start_time_;
    int interval_seconds = static_cast<int>(interval.InSeconds());
    // Record time in seconds over an interval of approximately 1 day.
    EXPERIMENT_CUSTOM_COUNTS(
        "Tabs.Discard.InitialTime2", interval_seconds, 1, 100000, 50);
  } else {
    // Not the first discard, so compute time since last discard.
    TimeDelta interval = TimeTicks::Now() - last_discard_time_;
    int interval_ms = static_cast<int>(interval.InMilliseconds());
    // Record time in milliseconds over an interval of approximately 1 day.
    // Start at 100 ms to get extra resolution in the target 750 ms range.
    EXPERIMENT_CUSTOM_COUNTS(
        "Tabs.Discard.IntervalTime2", interval_ms, 100, 100000 * 1000, 50);
  }
  // Record Chrome's concept of system memory usage at the time of the discard.
  base::SystemMemoryInfoKB memory;
  if (base::GetSystemMemoryInfo(&memory)) {
    int mem_anonymous_mb = (memory.active_anon + memory.inactive_anon) / 1024;
    EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB",
                                   mem_anonymous_mb);

    int mem_available_mb =
        (memory.active_file + memory.inactive_file + memory.free) / 1024;
    EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAvailableMB",
                                   mem_available_mb);
  }
  // Set up to record the next interval.
  last_discard_time_ = TimeTicks::Now();
}

int OomPriorityManager::GetTabCount() const {
  int tab_count = 0;
  for (BrowserList::const_iterator browser_it = BrowserList::begin();
      browser_it != BrowserList::end(); ++browser_it) {
    Browser* browser = *browser_it;
    tab_count += browser->tab_strip_model()->count();
  }
  return tab_count;
}

// Returns true if |first| is considered less desirable to be killed
// than |second|.
bool OomPriorityManager::CompareTabStats(TabStats first,
                                         TabStats second) {
  // Being currently selected is most important.
  if (first.is_selected != second.is_selected)
    return first.is_selected == true;

  // Being pinned is second most important.
  if (first.is_pinned != second.is_pinned)
    return first.is_pinned == true;

  // Being an app is important too, as you're the only visible surface in the
  // window and we don't want to discard that.
  if (first.is_app != second.is_app)
    return first.is_app == true;

  // TODO(jamescook): Incorporate sudden_termination_allowed into the sort
  // order.  We don't do this now because pages with unload handlers set
  // sudden_termination_allowed false, and that covers too many common pages
  // with ad networks and statistics scripts.  Ideally we would like to check
  // for beforeUnload handlers, which are likely to present a dialog asking
  // if the user wants to discard state.  crbug.com/123049

  // Being more recently selected is more important.
  return first.last_selected > second.last_selected;
}

void OomPriorityManager::AdjustFocusedTabScoreOnFileThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
  content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(
      focused_tab_pid_, chrome::kLowestRendererOomScore);
  pid_to_oom_score_[focused_tab_pid_] = chrome::kLowestRendererOomScore;
}

void OomPriorityManager::OnFocusTabScoreAdjustmentTimeout() {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&OomPriorityManager::AdjustFocusedTabScoreOnFileThread,
                 base::Unretained(this)));
}

void OomPriorityManager::Observe(int type,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  base::ProcessHandle handle = 0;
  base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
  switch (type) {
    case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
      handle =
          content::Details<content::RenderProcessHost::RendererClosedDetails>(
              details)->handle;
      pid_to_oom_score_.erase(handle);
      break;
    }
    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
      handle = content::Source<content::RenderProcessHost>(source)->
          GetHandle();
      pid_to_oom_score_.erase(handle);
      break;
    }
    case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: {
      bool visible = *content::Details<bool>(details).ptr();
      if (visible) {
        focused_tab_pid_ =
            content::Source<content::RenderWidgetHost>(source).ptr()->
            GetProcess()->GetHandle();

        // If the currently focused tab already has a lower score, do not
        // set it. This can happen in case the newly focused tab is script
        // connected to the previous tab.
        ProcessScoreMap::iterator it;
        it = pid_to_oom_score_.find(focused_tab_pid_);
        if (it == pid_to_oom_score_.end()
            || it->second != chrome::kLowestRendererOomScore) {
          // By starting a timer we guarantee that the tab is focused for
          // certain amount of time. Secondly, it also does not add overhead
          // to the tab switching time.
          if (focus_tab_score_adjust_timer_.IsRunning())
            focus_tab_score_adjust_timer_.Reset();
          else
            focus_tab_score_adjust_timer_.Start(FROM_HERE,
              TimeDelta::FromMilliseconds(kFocusedTabScoreAdjustIntervalMs),
              this, &OomPriorityManager::OnFocusTabScoreAdjustmentTimeout);
        }
      }
      break;
    }
    default:
      NOTREACHED() << L"Received unexpected notification";
      break;
  }
}

// Here we collect most of the information we need to sort the
// existing renderers in priority order, and hand out oom_score_adj
// scores based on that sort order.
//
// Things we need to collect on the browser thread (because
// TabStripModel isn't thread safe):
// 1) whether or not a tab is pinned
// 2) last time a tab was selected
// 3) is the tab currently selected
void OomPriorityManager::AdjustOomPriorities() {
  if (BrowserList::size() == 0)
    return;

  // Check for a discontinuity in time caused by the machine being suspended.
  if (!last_adjust_time_.is_null()) {
    TimeDelta suspend_time = TimeTicks::Now() - last_adjust_time_;
    if (suspend_time.InSeconds() > kSuspendThresholdSeconds) {
      // We were probably suspended, move our event timers forward in time so
      // when we subtract them out later we are counting "uptime".
      start_time_ += suspend_time;
      if (!last_discard_time_.is_null())
        last_discard_time_ += suspend_time;
    }
  }
  last_adjust_time_ = TimeTicks::Now();

  TabStatsList stats_list = GetTabStatsOnUIThread();
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&OomPriorityManager::AdjustOomPrioritiesOnFileThread,
                 base::Unretained(this), stats_list));
}

OomPriorityManager::TabStatsList OomPriorityManager::GetTabStatsOnUIThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  TabStatsList stats_list;
  stats_list.reserve(32);  // 99% of users have < 30 tabs open
  bool browser_active = true;
  for (BrowserList::const_reverse_iterator browser_iterator =
           BrowserList::begin_last_active();
       browser_iterator != BrowserList::end_last_active();
       ++browser_iterator) {
    Browser* browser = *browser_iterator;
    bool is_browser_for_app = browser->is_app();
    const TabStripModel* model = browser->tab_strip_model();
    for (int i = 0; i < model->count(); i++) {
      WebContents* contents = model->GetTabContentsAt(i)->web_contents();
      if (!contents->IsCrashed()) {
        TabStats stats;
        stats.is_app = is_browser_for_app;
        stats.is_pinned = model->IsTabPinned(i);
        stats.is_selected = browser_active && model->IsTabSelected(i);
        stats.is_discarded = model->IsTabDiscarded(i);
        stats.last_selected = contents->GetLastSelectedTime();
        stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
        stats.title = contents->GetTitle();
        stats.tab_contents_id = IdFromTabContents(contents);
        stats_list.push_back(stats);
      }
    }
    // We process the active browser window in the first iteration.
    browser_active = false;
  }
  // Sort the data we collected so that least desirable to be
  // killed is first, most desirable is last.
  std::sort(stats_list.begin(), stats_list.end(), CompareTabStats);
  return stats_list;
}

void OomPriorityManager::AdjustOomPrioritiesOnFileThread(
    TabStatsList stats_list) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);

  // Now we assign priorities based on the sorted list.  We're
  // assigning priorities in the range of kLowestRendererOomScore to
  // kHighestRendererOomScore (defined in chrome_constants.h).
  // oom_score_adj takes values from -1000 to 1000.  Negative values
  // are reserved for system processes, and we want to give some room
  // below the range we're using to allow for things that want to be
  // above the renderers in priority, so the defined range gives us
  // some variation in priority without taking up the whole range.  In
  // the end, however, it's a pretty arbitrary range to use.  Higher
  // values are more likely to be killed by the OOM killer.
  //
  // We also remove any duplicate PIDs, leaving the most important
  // (least likely to be killed) of the duplicates, so that a
  // particular renderer process takes on the oom_score_adj of the
  // least likely tab to be killed.
  const int kPriorityRange = chrome::kHighestRendererOomScore -
                             chrome::kLowestRendererOomScore;
  float priority_increment =
      static_cast<float>(kPriorityRange) / stats_list.size();
  float priority = chrome::kLowestRendererOomScore;
  std::set<base::ProcessHandle> already_seen;
  int score = 0;
  ProcessScoreMap::iterator it;
  for (TabStatsList::iterator iterator = stats_list.begin();
       iterator != stats_list.end(); ++iterator) {
    // stats_list also contains discarded tab stat. If renderer_handler is zero,
    // we don't need to adjust oom_score.
    if (iterator->renderer_handle == 0)
      continue;
    if (already_seen.find(iterator->renderer_handle) == already_seen.end()) {
      already_seen.insert(iterator->renderer_handle);
      // If a process has the same score as the newly calculated value,
      // do not set it.
      score = static_cast<int>(priority + 0.5f);
      it = pid_to_oom_score_.find(iterator->renderer_handle);
      if (it == pid_to_oom_score_.end() || it->second != score) {
        content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(
            iterator->renderer_handle, score);
        pid_to_oom_score_[iterator->renderer_handle] = score;
      }
      priority += priority_increment;
    }
  }
}

}  // namespace chromeos


text:
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = components;

var _overwrite = require('utilise/overwrite');

var _overwrite2 = _interopRequireDefault(_overwrite);

var _includes = require('utilise/includes');

var _includes2 = _interopRequireDefault(_includes);

var _header = require('utilise/header');

var _header2 = _interopRequireDefault(_header);

var _client = require('utilise/client');

var _client2 = _interopRequireDefault(_client);

var _values = require('utilise/values');

var _values2 = _interopRequireDefault(_values);

var _proxy = require('utilise/proxy');

var _proxy2 = _interopRequireDefault(_proxy);

var _attr = require('utilise/attr');

var _attr2 = _interopRequireDefault(_attr);

var _noop = require('utilise/noop');

var _noop2 = _interopRequireDefault(_noop);

var _time = require('utilise/time');

var _time2 = _interopRequireDefault(_time);

var _key = require('utilise/key');

var _key2 = _interopRequireDefault(_key);

var _all = require('utilise/all');

var _all2 = _interopRequireDefault(_all);

var _is = require('utilise/is');

var _is2 = _interopRequireDefault(_is);

var _lo = require('utilise/lo');

var _lo2 = _interopRequireDefault(_lo);

var _data = require('./types/data');

var _data2 = _interopRequireDefault(_data);

var _fn = require('./types/fn');

var _fn2 = _interopRequireDefault(_fn);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// -------------------------------------------
// API: Renders specific nodes, resources or everything
// -------------------------------------------
// ripple.draw()                 - redraw all components on page
// ripple.draw(element)          - redraw specific element
// ripple.draw.call(element)     - redraw specific element
// ripple.draw.call(selection)   - redraw D3 selection
// ripple.draw('name')           - redraw elements that depend on resource
// ripple.draw({ ... })          - redraw elements that depend on resource
// MutationObserver(ripple.draw) - redraws element being observed

function components(ripple) {
  if (!_client2.default) return ripple;
  log('creating');

  (0, _values2.default)(ripple.types).map(function (type) {
    return type.parse = (0, _proxy2.default)(type.parse, clean(ripple));
  });
  (0, _key2.default)('types.application/javascript.render', function (d) {
    return (0, _fn2.default)(ripple);
  })(ripple);
  (0, _key2.default)('types.application/data.render', function (d) {
    return (0, _data2.default)(ripple);
  })(ripple);
  ripple.draw = Node.prototype.draw = draw(ripple);
  ripple.render = render(ripple);
  ripple.on('change.draw', ripple.draw);
  (0, _time2.default)(0, ripple.draw);
  return ripple;
}

// public draw api
function draw(ripple) {
  return function (thing) {
    return this && this.nodeName ? invoke(ripple)(this) : this && this.node ? invoke(ripple)(this.node()) : !thing ? everything(ripple) : thing instanceof mutation ? invoke(ripple)(thing.target) : thing[0] instanceof mutation ? invoke(ripple)(thing[0].target) : thing.nodeName ? invoke(ripple)(thing) : thing.node ? invoke(ripple)(thing.node()) : thing.name ? resource(ripple)(thing.name) : _is2.default.str(thing) ? resource(ripple)(thing) : err('could not update', thing);
  };
}

// render all components
var everything = function everything(ripple) {
  var selector = (0, _values2.default)(ripple.resources).filter((0, _header2.default)('content-type', 'application/javascript')).map((0, _key2.default)('name')).join(',');

  return !selector ? [] : (0, _all2.default)(selector).map(invoke(ripple));
};

// render all elements that depend on the resource
var resource = function resource(ripple) {
  return function (name) {
    var res = ripple.resources[name],
        type = (0, _header2.default)('content-type')(res);

    return (ripple.types[type].render || _noop2.default)(res);
  };
};

// batch renders on render frames
var batch = function batch(ripple) {
  return function (el) {
    if (!el.pending) {
      el.pending = [];
      requestAnimationFrame(function (d) {
        el.changes = el.pending;
        delete el.pending;
        ripple.render(el);
      });
    }

    if (ripple.change) el.pending.push(ripple.change[1]);
  };
};

// main function to render a particular custom element with any data it needs
var invoke = function invoke(ripple) {
  return function (el) {
    if (!(0, _includes2.default)('-')(el.nodeName)) return;
    if (el.nodeName == '#document-fragment') return invoke(ripple)(el.host);
    if (el.nodeName == '#text') return invoke(ripple)(el.parentNode);
    if (!el.matches(isAttached)) return;
    if ((0, _attr2.default)(el, 'inert') != null) return;
    return batch(ripple)(el), el;
  };
};

var render = function render(ripple) {
  return function (el) {
    var name = (0, _lo2.default)(el.tagName),
        deps = (0, _attr2.default)(el, 'data'),
        fn = body(ripple)(name),
        data = bodies(ripple)(deps),
        root = el.shadowRoot || el;

    if (!fn) return el;
    if (deps && !data) return el;

    try {
      fn.call(root, root, defaults(el, data));
    } catch (e) {
      err(e, e.stack);
    }

    return el;
  };
};

// clean local headers for transport
var clean = function clean(ripple) {
  return function (res) {
    return delete res.headers.pending, res;
  };
};

// helpers
var defaults = function defaults(el, data) {
  el.state = el.state || {};
  (0, _overwrite2.default)(el.state)(data);
  (0, _overwrite2.default)(el.state)(el.__data__);
  el.__data__ = el.state;
  return el.state;
};

var bodies = function bodies(ripple) {
  return function (deps) {
    var o = {},
        names = deps ? deps.split(' ') : [];

    names.map(function (d) {
      return o[d] = body(ripple)(d);
    });

    return !names.length ? undefined : (0, _values2.default)(o).some(_is2.default.falsy) ? undefined : o;
  };
};

var body = function body(ripple) {
  return function (name) {
    return ripple.resources[name] && ripple.resources[name].body;
  };
};

var index = function index(el) {
  return Array.prototype.indexOf.call((0, _key2.default)('parentNode.children')(el) || [], el);
};

var log = require('utilise/log')('[ri/components]'),
    err = require('utilise/err')('[ri/components]'),
    mutation = _client2.default && window.MutationRecord || _noop2.default,
    customs = _client2.default && !!document.registerElement,
    isAttached = customs ? 'html *, :host-context(html) *' : 'html *';
_client2.default && (Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector);

redpajama_set_name: RedPajamaGithub


text:
import React from 'react';
import Title from 'react-title-component';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import spacing from 'material-ui/styles/spacing';
import styleResizable from 'material-ui/utils/styleResizable';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import {darkWhite, lightWhite, grey900} from 'material-ui/styles/colors';
import AppNavDrawer from './AppNavDrawer';
import FullWidthSection from './FullWidthSection';

const githubButton = (
  <IconButton
    iconClassName="muidocs-icon-custom-github"
    href="https://github.com/callemall/material-ui"
    linkButton={true}
  />
);

const Master = React.createClass({

  propTypes: {
    children: React.PropTypes.node,
    location: React.PropTypes.object,
  },

  contextTypes: {
    router: React.PropTypes.object.isRequired,
  },

  childContextTypes: {
    muiTheme: React.PropTypes.object,
  },

  mixins: [
    styleResizable,
  ],

  getInitialState() {
    return {
      muiTheme: getMuiTheme(),
      navDrawerOpen: false,
    };
  },

  getChildContext() {
    return {
      muiTheme: this.state.muiTheme,
    };
  },

  componentWillMount() {
    this.setState({
      muiTheme: this.state.muiTheme,
    });
  },

  componentWillReceiveProps(nextProps, nextContext) {
    const newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
    this.setState({
      muiTheme: newMuiTheme,
    });
  },

  getStyles() {
    const styles = {
      appBar: {
        position: 'fixed',
        // Needed to overlap the examples
        zIndex: this.state.muiTheme.zIndex.appBar + 1,
        top: 0,
      },
      root: {
        paddingTop: spacing.desktopKeylineIncrement,
        minHeight: 400,
      },
      content: {
        margin: spacing.desktopGutter,
      },
      contentWhenMedium: {
        margin: `${spacing.desktopGutter * 2}px ${spacing.desktopGutter * 3}px`,
      },
      footer: {
        backgroundColor: grey900,
        textAlign: 'center',
      },
      a: {
        color: darkWhite,
      },
      p: {
        margin: '0 auto',
        padding: 0,
        color: lightWhite,
        maxWidth: 356,
      },
      iconButton: {
        color: darkWhite,
      },
    };

    if (this.isDeviceSize(styleResizable.statics.Sizes.MEDIUM) ||
        this.isDeviceSize(styleResizable.statics.Sizes.LARGE)) {
      styles.content = Object.assign(styles.content, styles.contentWhenMedium);
    }

    return styles;
  },

  handleTouchTapLeftIconButton() {
    this.setState({
      navDrawerOpen: !this.state.navDrawerOpen,
    });
  },

  handleChangeRequestNavDrawer(open) {
    this.setState({
      navDrawerOpen: open,
    });
  },

  handleChangeList(event, value) {
    this.context.router.push(value);
    this.setState({
      navDrawerOpen: false,
    });
  },

  handleChangeMuiTheme(muiTheme) {
    this.setState({
      muiTheme: muiTheme,
    });
  },

  render() {
    const {
      location,
      children,
    } = this.props;

    let {
      navDrawerOpen,
    } = this.state;

    const {
      prepareStyles,
    } = this.state.muiTheme;

    const router = this.context.router;
    const styles = this.getStyles();
    const title =
      router.isActive('/get-started') ? 'Get Started' :
      router.isActive('/customization') ? 'Customization' :
      router.isActive('/components') ? 'Components' :
      router.isActive('/discover-more') ? 'Discover More' : '';

    let docked = false;
    let showMenuIconButton = true;

    if (this.isDeviceSize(styleResizable.statics.Sizes.LARGE) && title !== '') {
      docked = true;
      navDrawerOpen = true;
      showMenuIconButton = false;

      styles.navDrawer = {
        zIndex: styles.appBar.zIndex - 1,
      };
      styles.root.paddingLeft = 256;
      styles.footer.paddingLeft = 256;
    }

    return (

        <Title render="Material-UI" />
        <AppBar
          onLeftIconButtonTouchTap={this.handleTouchTapLeftIconButton}
          title={title}
          zDepth={0}
          iconElementRight={githubButton}
          style={styles.appBar}
          showMenuIconButton={showMenuIconButton}
        />
        {title !== '' ?

              {React.cloneElement(children, {
                onChangeMuiTheme: this.handleChangeMuiTheme,
              })}

 :
          children
        }
        <AppNavDrawer
          style={styles.navDrawer}
          location={location}
          docked={docked}
          onRequestChangeNavDrawer={this.handleChangeRequestNavDrawer}
          onChangeList={this.handleChangeList}
          open={navDrawerOpen}
        />
        <FullWidthSection style={styles.footer}>

            {'Hand crafted with love by the engineers at '}

              Call-Em-All

            {' and our awesome '}

              contributors
            .

          <IconButton
            iconStyle={styles.iconButton}
            iconClassName="muidocs-icon-custom-github"
            href="https://github.com/callemall/material-ui"
            linkButton={true}
          />
        </FullWidthSection>

    );
  },
});

export default Master;


text:
import {request} from '../util'

// This is a helper class to manage the many to many models; that
// is, models who are associated to other models in a many-to-many
// relationship.
//
// In a SQL database, these are usually models that associate two
// other models together via foreign keys.

export default class ManyToManyModel {
  constructor (client, parentModelName, nestedModelName) {
    this.client = client
    this.parent = parentModelName
    this.nested = nestedModelName
  }

  create (id, nested_id, entity = '', opts) {
    return request(this.client, opts, {
      method: 'POST',
      path: `/${this.parent}/${id}/${this.nested}/${nested_id}`,
      entity: entity
    })
  }

  index (id, params, opts) {
    return request(this.client, opts, {
      path: `/${this.parent}/${id}/${this.nested}`,
      params: params
    })
  }

  get (id, nested_id, params, opts) {
    return request(this.client, opts, {
      path: `/${this.parent}/${id}/${this.nested}/${nested_id}`,
      params: params
    })
  }

  update (id, nested_id, entity = '', opts) {
    return request(this.client, opts, {
      method: 'PUT',
      path: `/${this.parent}/${id}/${this.nested}/${nested_id}`,
      entity: entity
    })
  }

  delete (id, nested_id, opts) {
    return request(this.client, opts, {
      method: 'DELETE',
      path: `/${this.parent}/${id}/${this.nested}/${nested_id}`
    })
  }
}


text:
<?php
namespace PHPTools\PHPHtmlDom\Core;

/**
* Esta clase peermite escribir los logs.
*/
class PHPHtmlDomLog extends \PHPTools\PHPErrorLog\PHPErrorLog
{
    /**
     * Arreglo con los mensajes de información.
     * @var array
     */
    protected static $info_msg = array(
        'I000' => '%s',
    );

    /**
     * Arreglo con los mensajes de error.
     * @var array
     */
    protected static $error_msg = array(
        'E000' => '%s',
        'E001' => 'El contenido (%.15s...) no parece ser un texto con formato HTML',
        'E002' => 'El contenido (%.15s...) no pudo ser convertido en un DOMDocument',
        'E003' => 'No se pudo convertir el selector (%s) en un DOMXPath',
    );

    /**
     * Arreglo con los mensajes de advertencia.
     * @var array
     */
    protected static $warn_msg = array(
        'W000' => '%s',
        'W001' => 'No se pudo Acceder al Contenido (%s)',
    );

    /**
     * Metodo que permite escribir un log de Error.
     * @param  string $msg_code Cadena de texto con el codigo del mensaje de error.
     * @param  array  $data     arreglo con los parametros necesarios para escribir el log.
     * @return void
     */
    final public function logError($msg_code,$data = array())
    {
        self::write(self::compileMessage(self::$error_msg[$msg_code],$data), PEL_ERROR);
    }

    /**
     * Metodo que permite escribir un log de Advertencia.
     * @param  string $msg_code Cadena de texto con el codigo del mensaje de advertencia.
     * @param  array  $data     arreglo con los parametros necesarios para escribir el log.
     * @return void
     */
    final public function logWarn($msg_code,$data = array())
    {
        self::write(self::compileMessage(self::$warn_msg[$msg_code],$data), PEL_WARNING);
    }

    /**
     * Metodo que permite escribir un log de Información.
     * @param  string $msg_code Cadena de texto con el codigo del mensaje de información.
     * @param  array  $data     arreglo con los parametros necesarios para escribir el log.
     * @return void
     */
    final public function logInfo($msg_code,$data = array())
    {
        self::write(self::compileMessage(self::$info_msg[$msg_code],$data), PEL_INFO);
    }

    /**
     * Metodo que permite compilar la cadena de texto del mensaje con sus parametros.
     * @param  string $msg  Cadena de texto con el mensaje.
     * @param  array $data  Arreglo con los parametros del mensaje.
     * @return string
     */
    private function compileMessage($msg,$data)
    {
        return sprintf("PHPHtmlDom: %s",vsprintf($msg,$data));
    }
}


text:
title: Never buy a Creative Zen Micro
author: ajordens
layout: post
permalink: /2006/09/never-buy-a-creative-zen-micro/
categories:
  - General Discussions
---
See [Creative Zen Micro Headphone Jack Fix][1]

I've had my zen micro for a little under 2 years and have been plagued by rather annoying headphone jack problems every 6 or 7 months. I say every 6 months because the first time I managed to have Creative repair it free of charge, but the second time Creative wanted $13 to talk to their support line about paying for a repair. I've been forced to run holding the connection in place for the past 4 months.

Now, out of principle, I'd rather not pay for hardware that breaks regularly for others and isn't particularly denied by Creative support folk (the last email correspondence ended with someone recommending that I try twisting and holding the headphone connection in place).

I'm not really an Apple fanatic, so the [Sandisk Sansa][2] looks appealing if and when I end up deciding to make another purchase. Anyone have experience with it?

It looks like Costco has it, an added bonus for nothing more than a convienent return policy.

 [1]: http://home.comcast.net/~mercx/
 [2]: http://www.sandisk.com/Products/Catalog(1166)-SanDisk_Sansa_e200_Series_MP3_Players.aspx


text:
#define pr_fmt(fmt) "%s: " fmt, __func__

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/aio_abi.h>
#include <linux/export.h>
#include <linux/syscalls.h>
#include <linux/backing-dev.h>
#include <linux/uio.h>

#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/mmu_context.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/aio.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/eventfd.h>
#include <linux/blkdev.h>
#include <linux/compat.h>
#include <linux/migrate.h>
#include <linux/ramfs.h>
#include <linux/percpu-refcount.h>
#include <linux/mount.h>

#include <asm/kmap_types.h>
#include <asm/uaccess.h>

#include "internal.h"

#define AIO_RING_MAGIC			0xa10a10a1
#define AIO_RING_COMPAT_FEATURES	1
#define AIO_RING_INCOMPAT_FEATURES	0
struct aio_ring {
	unsigned	id;	/* kernel internal index number */
	unsigned	nr;	/* number of io_events */
	unsigned	head;
	unsigned	tail;

	unsigned	magic;
	unsigned	compat_features;
	unsigned	incompat_features;
	unsigned	header_length;	/* size of aio_ring */

	struct io_event		io_events[0];
}; /* 128 bytes + ring size */

#define AIO_RING_PAGES	8

struct kioctx_table {
	struct rcu_head	rcu;
	unsigned	nr;
	struct kioctx	*table[];
};

struct kioctx_cpu {
	unsigned		reqs_available;
};

struct kioctx {
	struct percpu_ref	users;
	atomic_t		dead;

	struct percpu_ref	reqs;

	unsigned long		user_id;

	struct __percpu kioctx_cpu *cpu;

	/*
	 * For percpu reqs_available, number of slots we move to/from global
	 * counter at a time:
	 */
	unsigned		req_batch;
	/*
	 * This is what userspace passed to io_setup(), it's not used for
	 * anything but counting against the global max_reqs quota.
	 *
	 * The real limit is nr_events - 1, which will be larger (see
	 * aio_setup_ring())
	 */
	unsigned		max_reqs;

	/* Size of ringbuffer, in units of struct io_event */
	unsigned		nr_events;

	unsigned long		mmap_base;
	unsigned long		mmap_size;

	struct page		**ring_pages;
	long			nr_pages;

	struct work_struct	free_work;

	struct {
		/*
		 * This counts the number of available slots in the ringbuffer,
		 * so we avoid overflowing it: it's decremented (if positive)
		 * when allocating a kiocb and incremented when the resulting
		 * io_event is pulled off the ringbuffer.
		 *
		 * We batch accesses to it with a percpu version.
		 */
		atomic_t	reqs_available;
	} ____cacheline_aligned_in_smp;

	struct {
		spinlock_t	ctx_lock;
		struct list_head active_reqs;	/* used for cancellation */
	} ____cacheline_aligned_in_smp;

	struct {
		struct mutex	ring_lock;
		wait_queue_head_t wait;
	} ____cacheline_aligned_in_smp;

	struct {
		unsigned	tail;
		spinlock_t	completion_lock;
	} ____cacheline_aligned_in_smp;

	struct page		*internal_pages[AIO_RING_PAGES];
	struct file		*aio_ring_file;

	unsigned		id;
};

/*------ sysctl variables----*/
static DEFINE_SPINLOCK(aio_nr_lock);
unsigned long aio_nr;		/* current system wide number of aio requests */
unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
/*----end sysctl variables---*/

static struct kmem_cache	*kiocb_cachep;
static struct kmem_cache	*kioctx_cachep;

static struct vfsmount *aio_mnt;

static const struct file_operations aio_ring_fops;
static const struct address_space_operations aio_ctx_aops;

static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
{
	struct qstr this = QSTR_INIT("[aio]", 5);
	struct file *file;
	struct path path;
	struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
	if (IS_ERR(inode))
		return ERR_CAST(inode);

	inode->i_mapping->a_ops = &aio_ctx_aops;
	inode->i_mapping->private_data = ctx;
	inode->i_size = PAGE_SIZE * nr_pages;

	path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
	if (!path.dentry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	path.mnt = mntget(aio_mnt);

	d_instantiate(path.dentry, inode);
	file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &aio_ring_fops);
	if (IS_ERR(file)) {
		path_put(&path);
		return file;
	}

	file->f_flags = O_RDWR;
	file->private_data = ctx;
	return file;
}

static struct dentry *aio_mount(struct file_system_type *fs_type,
				int flags, const char *dev_name, void *data)
{
	static const struct dentry_operations ops = {
		.d_dname	= simple_dname,
	};
	return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1);
}

/* aio_setup
 *	Creates the slab caches used by the aio routines, panic on
 *	failure as this is done early during the boot sequence.
 */
static int __init aio_setup(void)
{
	static struct file_system_type aio_fs = {
		.name		= "aio",
		.mount		= aio_mount,
		.kill_sb	= kill_anon_super,
	};
	aio_mnt = kern_mount(&aio_fs);
	if (IS_ERR(aio_mnt))
		panic("Failed to create aio fs mount.");

	kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
	kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);

	pr_debug("sizeof(struct page) = %zu\n", sizeof(struct page));

	return 0;
}
__initcall(aio_setup);

static void put_aio_ring_file(struct kioctx *ctx)
{
	struct file *aio_ring_file = ctx->aio_ring_file;
	if (aio_ring_file) {
		truncate_setsize(aio_ring_file->f_inode, 0);

		/* Prevent further access to the kioctx from migratepages */
		spin_lock(&aio_ring_file->f_inode->i_mapping->private_lock);
		aio_ring_file->f_inode->i_mapping->private_data = NULL;
		ctx->aio_ring_file = NULL;
		spin_unlock(&aio_ring_file->f_inode->i_mapping->private_lock);

		fput(aio_ring_file);
	}
}

static void aio_free_ring(struct kioctx *ctx)
{
	int i;

	for (i = 0; i < ctx->nr_pages; i++) {
		struct page *page;
		pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
				page_count(ctx->ring_pages[i]));
		page = ctx->ring_pages[i];
		if (!page)
			continue;
		ctx->ring_pages[i] = NULL;
		put_page(page);
	}

	put_aio_ring_file(ctx);

	if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) {
		kfree(ctx->ring_pages);
		ctx->ring_pages = NULL;
	}
}

static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
{
	vma->vm_ops = &generic_file_vm_ops;
	return 0;
}

static const struct file_operations aio_ring_fops = {
	.mmap = aio_ring_mmap,
};

static int aio_set_page_dirty(struct page *page)
{
	return 0;
}

#if IS_ENABLED(CONFIG_MIGRATION)
static int aio_migratepage(struct address_space *mapping, struct page *new,
			struct page *old, enum migrate_mode mode)
{
	struct kioctx *ctx;
	unsigned long flags;
	int rc;

	rc = 0;

	/* Make sure the old page hasn't already been changed */
	spin_lock(&mapping->private_lock);
	ctx = mapping->private_data;
	if (ctx) {
		pgoff_t idx;
		spin_lock_irqsave(&ctx->completion_lock, flags);
		idx = old->index;
		if (idx < (pgoff_t)ctx->nr_pages) {
			if (ctx->ring_pages[idx] != old)
				rc = -EAGAIN;
		} else
			rc = -EINVAL;
		spin_unlock_irqrestore(&ctx->completion_lock, flags);
	} else
		rc = -EINVAL;
	spin_unlock(&mapping->private_lock);

	if (rc != 0)
		return rc;

	/* Writeback must be complete */
	BUG_ON(PageWriteback(old));
	get_page(new);

	rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
	if (rc != MIGRATEPAGE_SUCCESS) {
		put_page(new);
		return rc;
	}

	/* We can potentially race against kioctx teardown here.  Use the
	 * address_space's private data lock to protect the mapping's
	 * private_data.
	 */
	spin_lock(&mapping->private_lock);
	ctx = mapping->private_data;
	if (ctx) {
		pgoff_t idx;
		spin_lock_irqsave(&ctx->completion_lock, flags);
		migrate_page_copy(new, old);
		idx = old->index;
		if (idx < (pgoff_t)ctx->nr_pages) {
			/* And only do the move if things haven't changed */
			if (ctx->ring_pages[idx] == old)
				ctx->ring_pages[idx] = new;
			else
				rc = -EAGAIN;
		} else
			rc = -EINVAL;
		spin_unlock_irqrestore(&ctx->completion_lock, flags);
	} else
		rc = -EBUSY;
	spin_unlock(&mapping->private_lock);

	if (rc == MIGRATEPAGE_SUCCESS)
		put_page(old);
	else
		put_page(new);

	return rc;
}
#endif

static const struct address_space_operations aio_ctx_aops = {
	.set_page_dirty = aio_set_page_dirty,
#if IS_ENABLED(CONFIG_MIGRATION)
	.migratepage	= aio_migratepage,
#endif
};

static int aio_setup_ring(struct kioctx *ctx)
{
	struct aio_ring *ring;
	unsigned nr_events = ctx->max_reqs;
	struct mm_struct *mm = current->mm;
	unsigned long size, unused;
	int nr_pages;
	int i;
	struct file *file;

	/* Compensate for the ring buffer's head/tail overlap entry */
	nr_events += 2;	/* 1 is required, 2 for good luck */

	size = sizeof(struct aio_ring);
	size += sizeof(struct io_event) * nr_events;

	nr_pages = PFN_UP(size);
	if (nr_pages < 0)
		return -EINVAL;

	file = aio_private_file(ctx, nr_pages);
	if (IS_ERR(file)) {
		ctx->aio_ring_file = NULL;
		return -EAGAIN;
	}

	ctx->aio_ring_file = file;
	nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
			/ sizeof(struct io_event);

	ctx->ring_pages = ctx->internal_pages;
	if (nr_pages > AIO_RING_PAGES) {
		ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
					  GFP_KERNEL);
		if (!ctx->ring_pages) {
			put_aio_ring_file(ctx);
			return -ENOMEM;
		}
	}

	for (i = 0; i < nr_pages; i++) {
		struct page *page;
		page = find_or_create_page(file->f_inode->i_mapping,
					   i, GFP_HIGHUSER | __GFP_ZERO);
		if (!page)
			break;
		pr_debug("pid(%d) page[%d]->count=%d\n",
			 current->pid, i, page_count(page));
		SetPageUptodate(page);
		SetPageDirty(page);
		unlock_page(page);

		ctx->ring_pages[i] = page;
	}
	ctx->nr_pages = i;

	if (unlikely(i != nr_pages)) {
		aio_free_ring(ctx);
		return -EAGAIN;
	}

	ctx->mmap_size = nr_pages * PAGE_SIZE;
	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);

	down_write(&mm->mmap_sem);
	ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
				       PROT_READ | PROT_WRITE,
				       MAP_SHARED, 0, &unused);
	up_write(&mm->mmap_sem);
	if (IS_ERR((void *)ctx->mmap_base)) {
		ctx->mmap_size = 0;
		aio_free_ring(ctx);
		return -EAGAIN;
	}

	pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);

	ctx->user_id = ctx->mmap_base;
	ctx->nr_events = nr_events; /* trusted copy */

	ring = kmap_atomic(ctx->ring_pages[0]);
	ring->nr = nr_events;	/* user copy */
	ring->id = ~0U;
	ring->head = ring->tail = 0;
	ring->magic = AIO_RING_MAGIC;
	ring->compat_features = AIO_RING_COMPAT_FEATURES;
	ring->incompat_features = AIO_RING_INCOMPAT_FEATURES;
	ring->header_length = sizeof(struct aio_ring);
	kunmap_atomic(ring);
	flush_dcache_page(ctx->ring_pages[0]);

	return 0;
}

#define AIO_EVENTS_PER_PAGE	(PAGE_SIZE / sizeof(struct io_event))
#define AIO_EVENTS_FIRST_PAGE	((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
#define AIO_EVENTS_OFFSET	(AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)

void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
{
	struct kioctx *ctx = req->ki_ctx;
	unsigned long flags;

	spin_lock_irqsave(&ctx->ctx_lock, flags);

	if (!req->ki_list.next)
		list_add(&req->ki_list, &ctx->active_reqs);

	req->ki_cancel = cancel;

	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
}
EXPORT_SYMBOL(kiocb_set_cancel_fn);

static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb)
{
	kiocb_cancel_fn *old, *cancel;

	/*
	 * Don't want to set kiocb->ki_cancel = KIOCB_CANCELLED unless it
	 * actually has a cancel function, hence the cmpxchg()
	 */

	cancel = ACCESS_ONCE(kiocb->ki_cancel);
	do {
		if (!cancel || cancel == KIOCB_CANCELLED)
			return -EINVAL;

		old = cancel;
		cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
	} while (cancel != old);

	return cancel(kiocb);
}

static void free_ioctx(struct work_struct *work)
{
	struct kioctx *ctx = container_of(work, struct kioctx, free_work);

	pr_debug("freeing %p\n", ctx);

	aio_free_ring(ctx);
	free_percpu(ctx->cpu);
	kmem_cache_free(kioctx_cachep, ctx);
}

static void free_ioctx_reqs(struct percpu_ref *ref)
{
	struct kioctx *ctx = container_of(ref, struct kioctx, reqs);

	INIT_WORK(&ctx->free_work, free_ioctx);
	schedule_work(&ctx->free_work);
}

/*
 * When this function runs, the kioctx has been removed from the "hash table"
 * and ctx->users has dropped to 0, so we know no more kiocbs can be submitted -
 * now it's safe to cancel any that need to be.
 */
static void free_ioctx_users(struct percpu_ref *ref)
{
	struct kioctx *ctx = container_of(ref, struct kioctx, users);
	struct kiocb *req;

	spin_lock_irq(&ctx->ctx_lock);

	while (!list_empty(&ctx->active_reqs)) {
		req = list_first_entry(&ctx->active_reqs,
				       struct kiocb, ki_list);

		list_del_init(&req->ki_list);
		kiocb_cancel(ctx, req);
	}

	spin_unlock_irq(&ctx->ctx_lock);

	percpu_ref_kill(&ctx->reqs);
	percpu_ref_put(&ctx->reqs);
}

static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
{
	unsigned i, new_nr;
	struct kioctx_table *table, *old;
	struct aio_ring *ring;

	spin_lock(&mm->ioctx_lock);
	rcu_read_lock();
	table = rcu_dereference(mm->ioctx_table);

	while (1) {
		if (table)
			for (i = 0; i < table->nr; i++)
				if (!table->table[i]) {
					ctx->id = i;
					table->table[i] = ctx;
					rcu_read_unlock();
					spin_unlock(&mm->ioctx_lock);

					ring = kmap_atomic(ctx->ring_pages[0]);
					ring->id = ctx->id;
					kunmap_atomic(ring);
					return 0;
				}

		new_nr = (table ? table->nr : 1) * 4;

		rcu_read_unlock();
		spin_unlock(&mm->ioctx_lock);

		table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) *
				new_nr, GFP_KERNEL);
		if (!table)
			return -ENOMEM;

		table->nr = new_nr;

		spin_lock(&mm->ioctx_lock);
		rcu_read_lock();
		old = rcu_dereference(mm->ioctx_table);

		if (!old) {
			rcu_assign_pointer(mm->ioctx_table, table);
		} else if (table->nr > old->nr) {
			memcpy(table->table, old->table,
			       old->nr * sizeof(struct kioctx *));

			rcu_assign_pointer(mm->ioctx_table, table);
			kfree_rcu(old, rcu);
		} else {
			kfree(table);
			table = old;
		}
	}
}

static void aio_nr_sub(unsigned nr)
{
	spin_lock(&aio_nr_lock);
	if (WARN_ON(aio_nr - nr > aio_nr))
		aio_nr = 0;
	else
		aio_nr -= nr;
	spin_unlock(&aio_nr_lock);
}

/* ioctx_alloc
 *	Allocates and initializes an ioctx.  Returns an ERR_PTR if it failed.
 */
static struct kioctx *ioctx_alloc(unsigned nr_events)
{
	struct mm_struct *mm = current->mm;
	struct kioctx *ctx;
	int err = -ENOMEM;

	/*
	 * We keep track of the number of available ringbuffer slots, to prevent
	 * overflow (reqs_available), and we also use percpu counters for this.
	 *
	 * So since up to half the slots might be on other cpu's percpu counters
	 * and unavailable, double nr_events so userspace sees what they
	 * expected: additionally, we move req_batch slots to/from percpu
	 * counters at a time, so make sure that isn't 0:
	 */
	nr_events = max(nr_events, num_possible_cpus() * 4);
	nr_events *= 2;

	/* Prevent overflows */
	if ((nr_events > (0x10000000U / sizeof(struct io_event))) ||
	    (nr_events > (0x10000000U / sizeof(struct kiocb)))) {
		pr_debug("ENOMEM: nr_events too high\n");
		return ERR_PTR(-EINVAL);
	}

	if (!nr_events || (unsigned long)nr_events > (aio_max_nr * 2UL))
		return ERR_PTR(-EAGAIN);

	ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
	if (!ctx)
		return ERR_PTR(-ENOMEM);

	ctx->max_reqs = nr_events;

	if (percpu_ref_init(&ctx->users, free_ioctx_users))
		goto err;

	if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs))
		goto err;

	spin_lock_init(&ctx->ctx_lock);
	spin_lock_init(&ctx->completion_lock);
	mutex_init(&ctx->ring_lock);
	init_waitqueue_head(&ctx->wait);

	INIT_LIST_HEAD(&ctx->active_reqs);

	ctx->cpu = alloc_percpu(struct kioctx_cpu);
	if (!ctx->cpu)
		goto err;

	if (aio_setup_ring(ctx) < 0)
		goto err;

	atomic_set(&ctx->reqs_available, ctx->nr_events - 1);
	ctx->req_batch = (ctx->nr_events - 1) / (num_possible_cpus() * 4);
	if (ctx->req_batch < 1)
		ctx->req_batch = 1;

	/* limit the number of system wide aios */
	spin_lock(&aio_nr_lock);
	if (aio_nr + nr_events > (aio_max_nr * 2UL) ||
	    aio_nr + nr_events < aio_nr) {
		spin_unlock(&aio_nr_lock);
		err = -EAGAIN;
		goto err_ctx;
	}
	aio_nr += ctx->max_reqs;
	spin_unlock(&aio_nr_lock);

	percpu_ref_get(&ctx->users);	/* io_setup() will drop this ref */
	percpu_ref_get(&ctx->reqs);	/* free_ioctx_users() will drop this */

	err = ioctx_add_table(ctx, mm);
	if (err)
		goto err_cleanup;

	pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
		 ctx, ctx->user_id, mm, ctx->nr_events);
	return ctx;

err_cleanup:
	aio_nr_sub(ctx->max_reqs);
err_ctx:
	aio_free_ring(ctx);
err:
	free_percpu(ctx->cpu);
	free_percpu(ctx->reqs.pcpu_count);
	free_percpu(ctx->users.pcpu_count);
	kmem_cache_free(kioctx_cachep, ctx);
	pr_debug("error allocating ioctx %d\n", err);
	return ERR_PTR(err);
}

/* kill_ioctx
 *	Cancels all outstanding aio requests on an aio context.  Used
 *	when the processes owning a context have all exited to encourage
 *	the rapid destruction of the kioctx.
 */
static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
{
	if (!atomic_xchg(&ctx->dead, 1)) {
		struct kioctx_table *table;

		spin_lock(&mm->ioctx_lock);
		rcu_read_lock();
		table = rcu_dereference(mm->ioctx_table);

		WARN_ON(ctx != table->table[ctx->id]);
		table->table[ctx->id] = NULL;
		rcu_read_unlock();
		spin_unlock(&mm->ioctx_lock);

		/* percpu_ref_kill() will do the necessary call_rcu() */
		wake_up_all(&ctx->wait);

		/*
		 * It'd be more correct to do this in free_ioctx(), after all
		 * the outstanding kiocbs have finished - but by then io_destroy
		 * has already returned, so io_setup() could potentially return
		 * -EAGAIN with no ioctxs actually in use (as far as userspace
		 *  could tell).
		 */
		aio_nr_sub(ctx->max_reqs);

		if (ctx->mmap_size)
			vm_munmap(ctx->mmap_base, ctx->mmap_size);

		percpu_ref_kill(&ctx->users);
	}
}

/* wait_on_sync_kiocb:
 *	Waits on the given sync kiocb to complete.
 */
ssize_t wait_on_sync_kiocb(struct kiocb *req)
{
	while (!req->ki_ctx) {
		set_current_state(TASK_UNINTERRUPTIBLE);
		if (req->ki_ctx)
			break;
		io_schedule();
	}
	__set_current_state(TASK_RUNNING);
	return req->ki_user_data;
}
EXPORT_SYMBOL(wait_on_sync_kiocb);

/*
 * exit_aio: called when the last user of mm goes away.  At this point, there is
 * no way for any new requests to be submited or any of the io_* syscalls to be
 * called on the context.
 *
 * There may be outstanding kiocbs, but free_ioctx() will explicitly wait on
 * them.
 */
void exit_aio(struct mm_struct *mm)
{
	struct kioctx_table *table;
	struct kioctx *ctx;
	unsigned i = 0;

	while (1) {
		rcu_read_lock();
		table = rcu_dereference(mm->ioctx_table);

		do {
			if (!table || i >= table->nr) {
				rcu_read_unlock();
				rcu_assign_pointer(mm->ioctx_table, NULL);
				if (table)
					kfree(table);
				return;
			}

			ctx = table->table[i++];
		} while (!ctx);

		rcu_read_unlock();

		/*
		 * We don't need to bother with munmap() here -
		 * exit_mmap(mm) is coming and it'll unmap everything.
		 * Since aio_free_ring() uses non-zero ->mmap_size
		 * as indicator that it needs to unmap the area,
		 * just set it to 0; aio_free_ring() is the only
		 * place that uses ->mmap_size, so it's safe.
		 */
		ctx->mmap_size = 0;

		kill_ioctx(mm, ctx);
	}
}

static void put_reqs_available(struct kioctx *ctx, unsigned nr)
{
	struct kioctx_cpu *kcpu;

	preempt_disable();
	kcpu = this_cpu_ptr(ctx->cpu);

	kcpu->reqs_available += nr;
	while (kcpu->reqs_available >= ctx->req_batch * 2) {
		kcpu->reqs_available -= ctx->req_batch;
		atomic_add(ctx->req_batch, &ctx->reqs_available);
	}

	preempt_enable();
}

static bool get_reqs_available(struct kioctx *ctx)
{
	struct kioctx_cpu *kcpu;
	bool ret = false;

	preempt_disable();
	kcpu = this_cpu_ptr(ctx->cpu);

	if (!kcpu->reqs_available) {
		int old, avail = atomic_read(&ctx->reqs_available);

		do {
			if (avail < ctx->req_batch)
				goto out;

			old = avail;
			avail = atomic_cmpxchg(&ctx->reqs_available,
					       avail, avail - ctx->req_batch);
		} while (avail != old);

		kcpu->reqs_available += ctx->req_batch;
	}

	ret = true;
	kcpu->reqs_available--;
out:
	preempt_enable();
	return ret;
}

/* aio_get_req
 *	Allocate a slot for an aio request.
 * Returns NULL if no requests are free.
 */
static inline struct kiocb *aio_get_req(struct kioctx *ctx)
{
	struct kiocb *req;

	if (!get_reqs_available(ctx))
		return NULL;

	req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO);
	if (unlikely(!req))
		goto out_put;

	percpu_ref_get(&ctx->reqs);

	req->ki_ctx = ctx;
	return req;
out_put:
	put_reqs_available(ctx, 1);
	return NULL;
}

static void kiocb_free(struct kiocb *req)
{
	if (req->ki_filp)
		fput(req->ki_filp);
	if (req->ki_eventfd != NULL)
		eventfd_ctx_put(req->ki_eventfd);
	kmem_cache_free(kiocb_cachep, req);
}

static struct kioctx *lookup_ioctx(unsigned long ctx_id)
{
	struct aio_ring __user *ring  = (void __user *)ctx_id;
	struct mm_struct *mm = current->mm;
	struct kioctx *ctx, *ret = NULL;
	struct kioctx_table *table;
	unsigned id;

	if (get_user(id, &ring->id))
		return NULL;

	rcu_read_lock();
	table = rcu_dereference(mm->ioctx_table);

	if (!table || id >= table->nr)
		goto out;

	ctx = table->table[id];
	if (ctx && ctx->user_id == ctx_id) {
		percpu_ref_get(&ctx->users);
		ret = ctx;
	}
out:
	rcu_read_unlock();
	return ret;
}

/* aio_complete
 *	Called when the io request on the given iocb is complete.
 */
void aio_complete(struct kiocb *iocb, long res, long res2)
{
	struct kioctx	*ctx = iocb->ki_ctx;
	struct aio_ring	*ring;
	struct io_event	*ev_page, *event;
	unsigned long	flags;
	unsigned tail, pos;

	/*
	 * Special case handling for sync iocbs:
	 *  - events go directly into the iocb for fast handling
	 *  - the sync task with the iocb in its stack holds the single iocb
	 *    ref, no other paths have a way to get another ref
	 *  - the sync task helpfully left a reference to itself in the iocb
	 */
	if (is_sync_kiocb(iocb)) {
		iocb->ki_user_data = res;
		smp_wmb();
		iocb->ki_ctx = ERR_PTR(-EXDEV);
		wake_up_process(iocb->ki_obj.tsk);
		return;
	}

	if (iocb->ki_list.next) {
		unsigned long flags;

		spin_lock_irqsave(&ctx->ctx_lock, flags);
		list_del(&iocb->ki_list);
		spin_unlock_irqrestore(&ctx->ctx_lock, flags);
	}

	/*
	 * Add a completion event to the ring buffer. Must be done holding
	 * ctx->completion_lock to prevent other code from messing with the tail
	 * pointer since we might be called from irq context.
	 */
	spin_lock_irqsave(&ctx->completion_lock, flags);

	tail = ctx->tail;
	pos = tail + AIO_EVENTS_OFFSET;

	if (++tail >= ctx->nr_events)
		tail = 0;

	ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
	event = ev_page + pos % AIO_EVENTS_PER_PAGE;

	event->obj = (u64)(unsigned long)iocb->ki_obj.user;
	event->data = iocb->ki_user_data;
	event->res = res;
	event->res2 = res2;

	kunmap_atomic(ev_page);
	flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);

	pr_debug("%p[%u]: %p: %p %Lx %lx %lx\n",
		 ctx, tail, iocb, iocb->ki_obj.user, iocb->ki_user_data,
		 res, res2);

	/* after flagging the request as done, we
	 * must never even look at it again
	 */
	smp_wmb();	/* make event visible before updating tail */

	ctx->tail = tail;

	ring = kmap_atomic(ctx->ring_pages[0]);
	ring->tail = tail;
	kunmap_atomic(ring);
	flush_dcache_page(ctx->ring_pages[0]);

	spin_unlock_irqrestore(&ctx->completion_lock, flags);

	pr_debug("added to ring %p at [%u]\n", iocb, tail);

	/*
	 * Check if the user asked us to deliver the result through an
	 * eventfd. The eventfd_signal() function is safe to be called
	 * from IRQ context.
	 */
	if (iocb->ki_eventfd != NULL)
		eventfd_signal(iocb->ki_eventfd, 1);

	/* everything turned out well, dispose of the aiocb. */
	kiocb_free(iocb);

	/*
	 * We have to order our ring_info tail store above and test
	 * of the wait list below outside the wait lock.  This is
	 * like in wake_up_bit() where clearing a bit has to be
	 * ordered with the unlocked test.
	 */
	smp_mb();

	if (waitqueue_active(&ctx->wait))
		wake_up(&ctx->wait);

	percpu_ref_put(&ctx->reqs);
}
EXPORT_SYMBOL(aio_complete);

/* aio_read_events
 *	Pull an event off of the ioctx's event ring.  Returns the number of
 *	events fetched
 */
static long aio_read_events_ring(struct kioctx *ctx,
				 struct io_event __user *event, long nr)
{
	struct aio_ring *ring;
	unsigned head, tail, pos;
	long ret = 0;
	int copy_ret;

	mutex_lock(&ctx->ring_lock);

	ring = kmap_atomic(ctx->ring_pages[0]);
	head = ring->head;
	tail = ring->tail;
	kunmap_atomic(ring);

	pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events);

	if (head == tail)
		goto out;

	while (ret < nr) {
		long avail;
		struct io_event *ev;
		struct page *page;

		avail = (head <= tail ?  tail : ctx->nr_events) - head;
		if (head == tail)
			break;

		avail = min(avail, nr - ret);
		avail = min_t(long, avail, AIO_EVENTS_PER_PAGE -
			    ((head + AIO_EVENTS_OFFSET) % AIO_EVENTS_PER_PAGE));

		pos = head + AIO_EVENTS_OFFSET;
		page = ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE];
		pos %= AIO_EVENTS_PER_PAGE;

		ev = kmap(page);
		copy_ret = copy_to_user(event + ret, ev + pos,
					sizeof(*ev) * avail);
		kunmap(page);

		if (unlikely(copy_ret)) {
			ret = -EFAULT;
			goto out;
		}

		ret += avail;
		head += avail;
		head %= ctx->nr_events;
	}

	ring = kmap_atomic(ctx->ring_pages[0]);
	ring->head = head;
	kunmap_atomic(ring);
	flush_dcache_page(ctx->ring_pages[0]);

	pr_debug("%li  h%u t%u\n", ret, head, tail);

	put_reqs_available(ctx, ret);
out:
	mutex_unlock(&ctx->ring_lock);

	return ret;
}

static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr,
			    struct io_event __user *event, long *i)
{
	long ret = aio_read_events_ring(ctx, event + *i, nr - *i);

	if (ret > 0)
		*i += ret;

	if (unlikely(atomic_read(&ctx->dead)))
		ret = -EINVAL;

	if (!*i)
		*i = ret;

	return ret < 0 || *i >= min_nr;
}

static long read_events(struct kioctx *ctx, long min_nr, long nr,
			struct io_event __user *event,
			struct timespec __user *timeout)
{
	ktime_t until = { .tv64 = KTIME_MAX };
	long ret = 0;

	if (timeout) {
		struct timespec	ts;

		if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
			return -EFAULT;

		until = timespec_to_ktime(ts);
	}

	/*
	 * Note that aio_read_events() is being called as the conditional - i.e.
	 * we're calling it after prepare_to_wait() has set task state to
	 * TASK_INTERRUPTIBLE.
	 *
	 * But aio_read_events() can block, and if it blocks it's going to flip
	 * the task state back to TASK_RUNNING.
	 *
	 * This should be ok, provided it doesn't flip the state back to
	 * TASK_RUNNING and return 0 too much - that causes us to spin. That
	 * will only happen if the mutex_lock() call blocks, and we then find
	 * the ringbuffer empty. So in practice we should be ok, but it's
	 * something to be aware of when touching this code.
	 */
	wait_event_interruptible_hrtimeout(ctx->wait,
			aio_read_events(ctx, min_nr, nr, event, &ret), until);

	if (!ret && signal_pending(current))
		ret = -EINTR;

	return ret;
}

/* sys_io_setup:
 *	Create an aio_context capable of receiving at least nr_events.
 *	ctxp must not point to an aio_context that already exists, and
 *	must be initialized to 0 prior to the call.  On successful
 *	creation of the aio_context, *ctxp is filled in with the resulting
 *	handle.  May fail with -EINVAL if *ctxp is not initialized,
 *	if the specified nr_events exceeds internal limits.  May fail
 *	with -EAGAIN if the specified nr_events exceeds the user's limit
 *	of available events.  May fail with -ENOMEM if insufficient kernel
 *	resources are available.  May fail with -EFAULT if an invalid
 *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
 *	implemented.
 */
SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
{
	struct kioctx *ioctx = NULL;
	unsigned long ctx;
	long ret;

	ret = get_user(ctx, ctxp);
	if (unlikely(ret))
		goto out;

	ret = -EINVAL;
	if (unlikely(ctx || nr_events == 0)) {
		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
		         ctx, nr_events);
		goto out;
	}

	ioctx = ioctx_alloc(nr_events);
	ret = PTR_ERR(ioctx);
	if (!IS_ERR(ioctx)) {
		ret = put_user(ioctx->user_id, ctxp);
		if (ret)
			kill_ioctx(current->mm, ioctx);
		percpu_ref_put(&ioctx->users);
	}

out:
	return ret;
}

/* sys_io_destroy:
 *	Destroy the aio_context specified.  May cancel any outstanding
 *	AIOs and block on completion.  Will fail with -ENOSYS if not
 *	implemented.  May fail with -EINVAL if the context pointed to
 *	is invalid.
 */
SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
{
	struct kioctx *ioctx = lookup_ioctx(ctx);
	if (likely(NULL != ioctx)) {
		kill_ioctx(current->mm, ioctx);
		percpu_ref_put(&ioctx->users);
		return 0;
	}
	pr_debug("EINVAL: io_destroy: invalid context id\n");
	return -EINVAL;
}

typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
			    unsigned long, loff_t);

static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
				     int rw, char __user *buf,
				     unsigned long *nr_segs,
				     struct iovec **iovec,
				     bool compat)
{
	ssize_t ret;

	*nr_segs = kiocb->ki_nbytes;

#ifdef CONFIG_COMPAT
	if (compat)
		ret = compat_rw_copy_check_uvector(rw,
				(struct compat_iovec __user *)buf,
				*nr_segs, 1, *iovec, iovec);
	else
#endif
		ret = rw_copy_check_uvector(rw,
				(struct iovec __user *)buf,
				*nr_segs, 1, *iovec, iovec);
	if (ret < 0)
		return ret;

	/* ki_nbytes now reflect bytes instead of segs */
	kiocb->ki_nbytes = ret;
	return 0;
}

static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
				       int rw, char __user *buf,
				       unsigned long *nr_segs,
				       struct iovec *iovec)
{
	if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
		return -EFAULT;

	iovec->iov_base = buf;
	iovec->iov_len = kiocb->ki_nbytes;
	*nr_segs = 1;
	return 0;
}

/*
 * aio_setup_iocb:
 *	Performs the initial checks and aio retry method
 *	setup for the kiocb at the time of io submission.
 */
static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
			    char __user *buf, bool compat)
{
	struct file *file = req->ki_filp;
	ssize_t ret;
	unsigned long nr_segs;
	int rw;
	fmode_t mode;
	aio_rw_op *rw_op;
	struct iovec inline_vec, *iovec = &inline_vec;

	switch (opcode) {
	case IOCB_CMD_PREAD:
	case IOCB_CMD_PREADV:
		mode	= FMODE_READ;
		rw	= READ;
		rw_op	= file->f_op->aio_read;
		goto rw_common;

	case IOCB_CMD_PWRITE:
	case IOCB_CMD_PWRITEV:
		mode	= FMODE_WRITE;
		rw	= WRITE;
		rw_op	= file->f_op->aio_write;
		goto rw_common;
rw_common:
		if (unlikely(!(file->f_mode & mode)))
			return -EBADF;

		if (!rw_op)
			return -EINVAL;

		ret = (opcode == IOCB_CMD_PREADV ||
		       opcode == IOCB_CMD_PWRITEV)
			? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
						&iovec, compat)
			: aio_setup_single_vector(req, rw, buf, &nr_segs,
						  iovec);
		if (ret)
			return ret;

		ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
		if (ret < 0) {
			if (iovec != &inline_vec)
				kfree(iovec);
			return ret;
		}

		req->ki_nbytes = ret;

		/* XXX: move/kill - rw_verify_area()? */
		/* This matches the pread()/pwrite() logic */
		if (req->ki_pos < 0) {
			ret = -EINVAL;
			break;
		}

		if (rw == WRITE)
			file_start_write(file);

		ret = rw_op(req, iovec, nr_segs, req->ki_pos);

		if (rw == WRITE)
			file_end_write(file);
		break;

	case IOCB_CMD_FDSYNC:
		if (!file->f_op->aio_fsync)
			return -EINVAL;

		ret = file->f_op->aio_fsync(req, 1);
		break;

	case IOCB_CMD_FSYNC:
		if (!file->f_op->aio_fsync)
			return -EINVAL;

		ret = file->f_op->aio_fsync(req, 0);
		break;

	default:
		pr_debug("EINVAL: no operation provided\n");
		return -EINVAL;
	}

	if (iovec != &inline_vec)
		kfree(iovec);

	if (ret != -EIOCBQUEUED) {
		/*
		 * There's no easy way to restart the syscall since other AIO's
		 * may be already running. Just fail this IO with EINTR.
		 */
		if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR ||
			     ret == -ERESTARTNOHAND ||
			     ret == -ERESTART_RESTARTBLOCK))
			ret = -EINTR;
		aio_complete(req, ret, 0);
	}

	return 0;
}

static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
			 struct iocb *iocb, bool compat)
{
	struct kiocb *req;
	ssize_t ret;

	/* enforce forwards compatibility on users */
	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
		pr_debug("EINVAL: reserve field set\n");
		return -EINVAL;
	}

	/* prevent overflows */
	if (unlikely(
	    (iocb->aio_buf != (unsigned long)iocb->aio_buf) ||
	    (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
	    ((ssize_t)iocb->aio_nbytes < 0)
	   )) {
		pr_debug("EINVAL: io_submit: overflow check\n");
		return -EINVAL;
	}

	req = aio_get_req(ctx);
	if (unlikely(!req))
		return -EAGAIN;

	req->ki_filp = fget(iocb->aio_fildes);
	if (unlikely(!req->ki_filp)) {
		ret = -EBADF;
		goto out_put_req;
	}

	if (iocb->aio_flags & IOCB_FLAG_RESFD) {
		/*
		 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
		 * instance of the file* now. The file descriptor must be
		 * an eventfd() fd, and will be signaled for each completed
		 * event using the eventfd_signal() function.
		 */
		req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd);
		if (IS_ERR(req->ki_eventfd)) {
			ret = PTR_ERR(req->ki_eventfd);
			req->ki_eventfd = NULL;
			goto out_put_req;
		}
	}

	ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
	if (unlikely(ret)) {
		pr_debug("EFAULT: aio_key\n");
		goto out_put_req;
	}

	req->ki_obj.user = user_iocb;
	req->ki_user_data = iocb->aio_data;
	req->ki_pos = iocb->aio_offset;
	req->ki_nbytes = iocb->aio_nbytes;

	ret = aio_run_iocb(req, iocb->aio_lio_opcode,
			   (char __user *)(unsigned long)iocb->aio_buf,
			   compat);
	if (ret)
		goto out_put_req;

	return 0;
out_put_req:
	put_reqs_available(ctx, 1);
	percpu_ref_put(&ctx->reqs);
	kiocb_free(req);
	return ret;
}

long do_io_submit(aio_context_t ctx_id, long nr,
		  struct iocb __user *__user *iocbpp, bool compat)
{
	struct kioctx *ctx;
	long ret = 0;
	int i = 0;
	struct blk_plug plug;

	if (unlikely(nr < 0))
		return -EINVAL;

	if (unlikely(nr > LONG_MAX/sizeof(*iocbpp)))
		nr = LONG_MAX/sizeof(*iocbpp);

	if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
		return -EFAULT;

	ctx = lookup_ioctx(ctx_id);
	if (unlikely(!ctx)) {
		pr_debug("EINVAL: invalid context id\n");
		return -EINVAL;
	}

	blk_start_plug(&plug);

	/*
	 * AKPM: should this return a partial result if some of the IOs were
	 * successfully submitted?
	 */
	for (i=0; i<nr; i++) {
		struct iocb __user *user_iocb;
		struct iocb tmp;

		if (unlikely(__get_user(user_iocb, iocbpp + i))) {
			ret = -EFAULT;
			break;
		}

		if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
			ret = -EFAULT;
			break;
		}

		ret = io_submit_one(ctx, user_iocb, &tmp, compat);
		if (ret)
			break;
	}
	blk_finish_plug(&plug);

	percpu_ref_put(&ctx->users);
	return i ? i : ret;
}

/* sys_io_submit:
 *	Queue the nr iocbs pointed to by iocbpp for processing.  Returns
 *	the number of iocbs queued.  May return -EINVAL if the aio_context
 *	specified by ctx_id is invalid, if nr is < 0, if the iocb at
 *	*iocbpp[0] is not properly initialized, if the operation specified
 *	is invalid for the file descriptor in the iocb.  May fail with
 *	-EFAULT if any of the data structures point to invalid data.  May
 *	fail with -EBADF if the file descriptor specified in the first
 *	iocb is invalid.  May fail with -EAGAIN if insufficient resources
 *	are available to queue any iocbs.  Will return 0 if nr is 0.  Will
 *	fail with -ENOSYS if not implemented.
 */
SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
		struct iocb __user * __user *, iocbpp)
{
	return do_io_submit(ctx_id, nr, iocbpp, 0);
}

/* lookup_kiocb
 *	Finds a given iocb for cancellation.
 */
static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
				  u32 key)
{
	struct list_head *pos;

	assert_spin_locked(&ctx->ctx_lock);

	if (key != KIOCB_KEY)
		return NULL;

	/* TODO: use a hash or array, this sucks. */
	list_for_each(pos, &ctx->active_reqs) {
		struct kiocb *kiocb = list_kiocb(pos);
		if (kiocb->ki_obj.user == iocb)
			return kiocb;
	}
	return NULL;
}

/* sys_io_cancel:
 *	Attempts to cancel an iocb previously passed to io_submit.  If
 *	the operation is successfully cancelled, the resulting event is
 *	copied into the memory pointed to by result without being placed
 *	into the completion queue and 0 is returned.  May fail with
 *	-EFAULT if any of the data structures pointed to are invalid.
 *	May fail with -EINVAL if aio_context specified by ctx_id is
 *	invalid.  May fail with -EAGAIN if the iocb specified was not
 *	cancelled.  Will fail with -ENOSYS if not implemented.
 */
SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
		struct io_event __user *, result)
{
	struct kioctx *ctx;
	struct kiocb *kiocb;
	u32 key;
	int ret;

	ret = get_user(key, &iocb->aio_key);
	if (unlikely(ret))
		return -EFAULT;

	ctx = lookup_ioctx(ctx_id);
	if (unlikely(!ctx))
		return -EINVAL;

	spin_lock_irq(&ctx->ctx_lock);

	kiocb = lookup_kiocb(ctx, iocb, key);
	if (kiocb)
		ret = kiocb_cancel(ctx, kiocb);
	else
		ret = -EINVAL;

	spin_unlock_irq(&ctx->ctx_lock);

	if (!ret) {
		/*
		 * The result argument is no longer used - the io_event is
		 * always delivered via the ring buffer. -EINPROGRESS indicates
		 * cancellation is progress:
		 */
		ret = -EINPROGRESS;
	}

	percpu_ref_put(&ctx->users);

	return ret;
}

/* io_getevents:
 *	Attempts to read at least min_nr events and up to nr events from
 *	the completion queue for the aio_context specified by ctx_id. If
 *	it succeeds, the number of read events is returned. May fail with
 *	-EINVAL if ctx_id is invalid, if min_nr is out of range, if nr is
 *	out of range, if timeout is out of range.  May fail with -EFAULT
 *	if any of the memory specified is invalid.  May return 0 or
 *	< min_nr if the timeout specified by timeout has elapsed
 *	before sufficient events are available, where timeout == NULL
 *	specifies an infinite timeout. Note that the timeout pointed to by
 *	timeout is relative.  Will fail with -ENOSYS if not implemented.
 */
SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
		long, min_nr,
		long, nr,
		struct io_event __user *, events,
		struct timespec __user *, timeout)
{
	struct kioctx *ioctx = lookup_ioctx(ctx_id);
	long ret = -EINVAL;

	if (likely(ioctx)) {
		if (likely(min_nr <= nr && min_nr >= 0))
			ret = read_events(ioctx, min_nr, nr, events, timeout);
		percpu_ref_put(&ioctx->users);
	}
	return ret;
}


text:
layout: post
title: "The Importance of Trial and Error"
date: "2016-11-24"
author: ["Athanasios Kritharis"]
---

### Introduction
Welcome everyone to the first of (hopefully) many blog posts for the UBC Chem-E-Car Team. The purpose of these posts is to give you, the reader insight into how our organization is run. Through this we hope to generate interest in our organization and to help get other students involved.

The topic of our first post is on the importance of trial and error. Most people will look at a finished product and comment on how sleek or amazing it is; while conveniently ignoring that it took years of tinkering and modifications for that item to even function properly!

First let's take a look at the first electronic circuit that I ever made for Chem-E-Car:

![First](/assets/images/blog/trial-and-error/first.jpg)

The entire device is a mess! There are wires everywhere, tons of unused board real estate, and parts that have to be tied together to fit on the board. Likewise, unsecured parts have a very unreliable connection and break off easily.

Over the summer I made a new model with the focus of eliminating loose wires and better utilizing space, this is the result:

![Second](/assets/images/blog/trial-and-error/second.jpg)

This model utilizes a lot less space, is easy to stack, and most of the components are stabilized on the board itself. However, during assembly I needed a lot of extra parts since directly soldering them often destroyed the part if not done properly. Another issue is that the model needed 4 stacks (making it really tall), and the lights and switches were not necessary. Now let's look at the second iteration:

![Third](/assets/images/blog/trial-and-error/third.jpg)

The board is even MORE compact, features detachable modules for easy replacement, and utilizes an SD card and opto-gate for recording data. However, the connectors were unreliable, the copper on the board was unprotected and prone to damage which destroyed the circuit at times, and data could not be read in real time.

To fix these issues I developed a 4th and final board:

![Fourth](/assets/images/blog/trial-and-error/fourth.jpg)

This system uses reliable connectors that can only be inserted in one direction, is completely modular (easy to replace destroyed parts), has a silkscreen layer that protects the circuit, only uses one layer, and utilizes a bluetooth system for real time data collection on a mobile phone!

Here is an image of all the circuits for an overall comparison:

![Comparison](/assets/images/blog/trial-and-error/comparison.jpg)

### Reflections

These circuits are 1.5 years of continuous design and iteration, with each model having its flaws analyzed and corrected. They were made by an entry level chemical engineering student with NO prior experience or knowledge of electronics. The moral of the story? Good design is all about making something, figuring out what works and doesn't work then rebuilding it until it sort of works.

![Quote](/assets/images/blog/trial-and-error/quote.jpg)

So, to any beginner in terms of design, don't despair! Rather look at what you can learn from your prototype and how it can be improved.

In that sense it is important to seek the feedback of experienced individuals. Their experience (in how NOT to do things wrong by doing it wrong) is invaluable for any would-be inventor. Look at how others have done things and learn accordingly from it. Finally remember, every master in a subject started from knowing nothing; the difference between them and the amateurs is that they never stopped trying to learn.


text:
JavaScript bundle for vim, this bundle provides syntax and indent plugins.

## A Quick Note on Regexes

Vim 7.4 was released recently, and unfortunately broke how this plugin
handles regexes. There was no real easy way for us to fix this unless we
completely rewrote how regexes work.

Good News: There was a recent update to Vim 7.4 that fixes this issue.

Make sure you are at least using Vim 7.4, with patches 1-7.

If you are stuck on an older version of Vim 7.4 with no way to update,
then simply perform the following commands to fix your current buffer:

```
:set regexpengine=1
:syntax enable
```

## Installation

### Install with [Vundle](https://github.com/gmarik/vundle)

Add to vimrc:

    Plugin 'pangloss/vim-javascript'

And install it:

    :so ~/.vimrc
    :PluginInstall

### Install with [pathogen](https://github.com/tpope/vim-pathogen)

      cd ~/.vim/bundle
      git clone https://github.com/pangloss/vim-javascript.git

## Configuration

The following variables control certain syntax highlighting features. You can
add them to your `.vimrc` to enable/disable their features.

#### javascript_enable_domhtmlcss

Enables HTML/CSS syntax highlighting in your JavaScript file.

Default Value: 0

#### b:javascript_fold

Enables JavaScript code folding.

Default Value: 1

#### javascript_ignore_javaScriptdoc

Disables JSDoc syntax highlighting

Default Value: 0

#### Concealing Characters

You can customize concealing characters by defining one or more of the following
variables:

    let g:javascript_conceal_function   = "ƒ"
    let g:javascript_conceal_null       = "ø"
    let g:javascript_conceal_this       = "@"
    let g:javascript_conceal_return     = "⇚"
    let g:javascript_conceal_undefined  = "¿"
    let g:javascript_conceal_NaN        = "ℕ"
    let g:javascript_conceal_prototype  = "¶"
    let g:javascript_conceal_static     = "•"
    let g:javascript_conceal_super      = "Ω"

## Contributing

This project uses the [git
flow](http://nvie.com/posts/a-successful-git-branching-model/) model for
development. There's [a handy git module for git
flow](//github.com/nvie/gitflow). If you'd like to be added as a contributor,
the price of admission is 1 pull request. Please follow the general code style
guides (read the code) and in your pull request explain the reason for the
proposed change and how it is valuable.

## Bug report

Report a bug on [GitHub Issues](https://github.com/pangloss/vim-javascript/issues).


text:
"use strict";
require.config({
  paths: {
    "jquery": "../../bower_components/jquery/jquery"
    ,"lodash": "../../bower_components/lodash/dist/lodash"
    ,"jquery.cookie": "../../bower_components/jquery.cookie/jquery.cookie"
    ,"jquery.leanmodal": "../lib/jquery.leanModal"
    ,"jq-console": "../../bower_components/jq-console/jqconsole.min"
    ,"bacon": "../../bower_components/bacon/dist/Bacon"
    ,"bacon.model": "../../bower_components/bacon.model/dist/bacon.model"
    ,"bacon.jquery": "../../bower_components/bacon.jquery/dist/bacon.jquery"
    ,"bacon.validation": "../../bower_components/bacon.validation/dist/bacon.validation"
    ,"handlebars": "../../bower_components/handlebars/handlebars.amd"
    ,"roy": "../lib/roy"
    ,"text": "../lib/text"
    ,"speak": "../speak.js/speakClient"
  },
  shim: {
    'jq-console': {
      deps: ["jquery"]
    }
    ,'jquery.leanmodal': {
      deps: ["jquery"]
    }
  },
  waitSeconds: 60
})
var turtle
require(["lodash", "jquery", "royenv", "royrepl", "turtle", "turtlebundle", "editor", "commands", "cookbook", "storage", "sharing", "cheatsheet", "help"],
    function(_, $, RoyEnv, RoyRepl, Turtle, TurtleBundle, Editor, Commands, Cookbook, storage, Sharing) {
  var overhead = 300
  if (window.self !== window.top) {
    $("body").addClass("embedded")
    overhead = 200
  }
  function width() { return $("body").width() }
  function height() {
    return Math.min(width() / 2, $(window).height() - overhead)
  }

  var element = $("#turtle-roy")
  var royEnv = RoyEnv()
  var repl = RoyRepl.init(element.find(".console"), royEnv)
  turtle = Turtle(element.find(".turtlegraphics"), width(), height())
  var editor = Editor(element, royEnv, repl)

  var loaded = TurtleBundle(royEnv, turtle, repl, editor).loaded

  loaded.onValue(function() {
    turtle.spin(360, 10)
    Cookbook(editor, repl)
    Sharing(editor.code, turtle)

    storage.openResult.onValue(function(turtle) {
      editor.reset()
      repl.paste(turtle.content.code)
      document.title = turtle.content.description + " -" + document.title
    })
    var queryParams = parseQuery(document.location.search)
    var turtleId = queryParams.turtle
    if (turtleId) {
      showEditor()
      storage.open(turtleId)
    } else if (queryParams.code) {
      showEditor()
      editor.reset()
      repl.paste(queryParams.code)
    }
    element.removeClass("loading")
    takeFocus()

  })

  element.find(".turtlegraphics").clickE().onValue(takeFocus)

  function showEditor() {
    element.toggleClass("editor-mode")
    takeFocus()
    editor.refresh()
  }

  element.find(".editor-link").asEventStream("click").onValue(showEditor)

  $(window).resize(function() {
    turtle.resize(width(), height())
  })

  function takeFocus() {
    if (element.find(".editor").is(":visible")) {
      element.find(".editor textarea").focus()
    } else {
      repl.focus()
    }
  }
})

function nonEmpty(x) { return x && x.length > 0 }

function parseQuery(qstr) {
  if (qstr == '') return {}
  var query = {}
  var a = qstr.substr(1).split('&')
  for (var i = 0; i < a.length; i++) {
    var b = a[i].split('=')
    query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '')
  }
  return query
}


text:
import * as creep from './b';

export function test(api) {
	api.eq(creep.a, 7);
	api.eq(creep.crawl(2), '99');

	try {
		creep.a = 5;
		return false;
	} catch(e) {
		return true;
	}

	return true;
}

export function name() {
	return "Export namespace declarations";
}


text:
<?php

namespace spec\Sylius\Component\Product\Model;

use Doctrine\Common\Collections\Collection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Association\Model\AssociableInterface;
use Sylius\Component\Product\Model\ArchetypeInterface;
use Sylius\Component\Product\Model\AttributeValueInterface;
use Sylius\Component\Product\Model\OptionInterface;
use Sylius\Component\Product\Model\ProductAssociationInterface;
use Sylius\Component\Product\Model\ProductInterface;
use Sylius\Component\Product\Model\VariantInterface;
use Sylius\Component\Resource\Model\ToggleableInterface;

/**
 * @author Paweł Jędrzejewski <pawel@sylius.org>
 * @author Gonzalo Vilaseca <gvilaseca@reiss.co.uk>
 */
class ProductSpec extends ObjectBehavior
{
    public function let()
    {
        $this->setCurrentLocale('en_US');
        $this->setFallbackLocale('en_US');
    }

    function it_is_initializable()
    {
        $this->shouldHaveType('Sylius\Component\Product\Model\Product');
    }

    function it_implements_Sylius_product_interface()
    {
        $this->shouldImplement(ProductInterface::class);
    }

    function it_implements_toggleable_interface()
    {
        $this->shouldImplement(ToggleableInterface::class);
    }

    function it_is_associatable()
    {
        $this->shouldImplement(AssociableInterface::class);
    }

    function it_has_no_id_by_default()
    {
        $this->getId()->shouldReturn(null);
    }

    function it_does_not_belong_to_any_archetype_by_default()
    {
        $this->getArchetype()->shouldReturn(null);
    }

    function it_can_belong_to_a_product_archetype(ArchetypeInterface $archetype)
    {
        $this->setArchetype($archetype);
        $this->getArchetype()->shouldReturn($archetype);
    }

    function it_has_no_name_by_default()
    {
        $this->getName()->shouldReturn(null);
    }

    function its_name_is_mutable()
    {
        $this->setName('Super product');
        $this->getName()->shouldReturn('Super product');
    }

    function it_has_no_slug_by_default()
    {
        $this->getSlug()->shouldReturn(null);
    }

    function its_slug_is_mutable()
    {
        $this->setSlug('super-product');
        $this->getSlug()->shouldReturn('super-product');
    }

    function it_has_no_description_by_default()
    {
        $this->getDescription()->shouldReturn(null);
    }

    function its_description_is_mutable()
    {
        $this->setDescription('This product is super cool because...');
        $this->getDescription()->shouldReturn('This product is super cool because...');
    }

    function it_initializes_availability_date_by_default()
    {
        $this->getAvailableOn()->shouldHaveType(\DateTime::class);
    }

    function it_is_available_by_default()
    {
        $this->shouldBeAvailable();
    }

    function its_availability_date_is_mutable()
    {
        $availableOn = new \DateTime('yesterday');

        $this->setAvailableOn($availableOn);
        $this->getAvailableOn()->shouldReturn($availableOn);
    }

    function it_is_available_only_if_availability_date_is_in_past()
    {
        $availableOn = new \DateTime('yesterday');

        $this->setAvailableOn($availableOn);
        $this->shouldBeAvailable();

        $availableOn = new \DateTime('tomorrow');

        $this->setAvailableOn($availableOn);
        $this->shouldNotBeAvailable();
    }

    function it_initializes_attribute_collection_by_default()
    {
        $this->getAttributes()->shouldHaveType('Doctrine\Common\Collections\Collection');
    }

    function it_adds_attribute(AttributeValueInterface $attribute)
    {
        $attribute->setProduct($this)->shouldBeCalled();

        $this->addAttribute($attribute);
        $this->hasAttribute($attribute)->shouldReturn(true);
    }

    function it_removes_attribute(AttributeValueInterface $attribute)
    {
        $attribute->setProduct($this)->shouldBeCalled();

        $this->addAttribute($attribute);
        $this->hasAttribute($attribute)->shouldReturn(true);

        $attribute->setProduct(null)->shouldBeCalled();

        $this->removeAttribute($attribute);
        $this->hasAttribute($attribute)->shouldReturn(false);
    }

    function it_should_not_have_master_variant_by_default()
    {
        $this->getMasterVariant()->shouldReturn(null);
    }

    function its_master_variant_should_be_mutable_and_define_given_variant_as_master(VariantInterface $variant)
    {
        $variant->setProduct($this)->shouldBeCalled();
        $variant->setMaster(true)->shouldBeCalled();

        $this->setMasterVariant($variant);
    }

    function it_should_not_add_master_variant_twice_to_collection(VariantInterface $variant)
    {
        $variant->isMaster()->willReturn(true);
        $variant->isDeleted()->willReturn(false);

        $variant->setProduct($this)->shouldBeCalled();
        $variant->setMaster(true)->shouldBeCalled();

        $this->setMasterVariant($variant);
        $this->setMasterVariant($variant);

        $this->hasVariants()->shouldReturn(false);
    }

    function its_hasVariants_should_return_false_if_no_variants_defined()
    {
        $this->hasVariants()->shouldReturn(false);
    }

    function its_hasVariants_should_return_true_only_if_any_variants_defined(VariantInterface $variant)
    {
        $variant->isMaster()->willReturn(false);
        $variant->isDeleted()->willReturn(false);

        $variant->setProduct($this)->shouldBeCalled();

        $this->addVariant($variant);
        $this->hasVariants()->shouldReturn(true);
    }

    function it_should_initialize_variants_collection_by_default()
    {
        $this->getVariants()->shouldHaveType('Doctrine\Common\Collections\Collection');
    }

    function it_should_initialize_option_collection_by_default()
    {
        $this->getOptions()->shouldHaveType('Doctrine\Common\Collections\Collection');
    }

    function its_hasOptions_should_return_false_if_no_options_defined()
    {
        $this->hasOptions()->shouldReturn(false);
    }

    function its_hasOptions_should_return_true_only_if_any_options_defined(OptionInterface $option)
    {
        $this->addOption($option);
        $this->hasOptions()->shouldReturn(true);
    }

    function its_options_collection_should_be_mutable(Collection $options)
    {
        $this->setOptions($options);
        $this->getOptions()->shouldReturn($options);
    }

    function it_should_add_option_properly(OptionInterface $option)
    {
        $this->addOption($option);
        $this->hasOption($option)->shouldReturn(true);
    }

    function it_should_remove_option_properly(OptionInterface $option)
    {
        $this->addOption($option);
        $this->hasOption($option)->shouldReturn(true);

        $this->removeOption($option);
        $this->hasOption($option)->shouldReturn(false);
    }

    function it_initializes_creation_date_by_default()
    {
        $this->getCreatedAt()->shouldHaveType(\DateTime::class);
    }

    function its_creation_date_is_mutable()
    {
        $date = new \DateTime('last year');

        $this->setCreatedAt($date);
        $this->getCreatedAt()->shouldReturn($date);
    }

    function it_has_no_last_update_date_by_default()
    {
        $this->getUpdatedAt()->shouldReturn(null);
    }

    function its_last_update_date_is_mutable()
    {
        $date = new \DateTime('last year');

        $this->setUpdatedAt($date);
        $this->getUpdatedAt()->shouldReturn($date);
    }

    function it_has_no_deletion_date_by_default()
    {
        $this->getDeletedAt()->shouldReturn(null);
    }

    function it_is_not_be_deleted_by_default()
    {
        $this->shouldNotBeDeleted();
    }

    function its_deletion_date_is_mutable()
    {
        $deletedAt = new \DateTime();

        $this->setDeletedAt($deletedAt);
        $this->getDeletedAt()->shouldReturn($deletedAt);
    }

    function it_is_deleted_only_if_deletion_date_is_in_past()
    {
        $deletedAt = new \DateTime('yesterday');

        $this->setDeletedAt($deletedAt);
        $this->shouldBeDeleted();

        $deletedAt = new \DateTime('tomorrow');

        $this->setDeletedAt($deletedAt);
        $this->shouldNotBeDeleted();
    }

    function it_is_enabled_by_default()
    {
        $this->shouldBeEnabled();
    }

    function it_is_toggleable()
    {
        $this->disable();
        $this->shouldNotBeEnabled();

        $this->enable();
        $this->shouldBeEnabled();
    }

    function it_adds_association(ProductAssociationInterface $association)
    {
        $association->setOwner($this)->shouldBeCalled();
        $this->addAssociation($association);

        $this->hasAssociation($association)->shouldReturn(true);
    }

    function it_allows_to_remove_association(ProductAssociationInterface $association)
    {
        $association->setOwner($this)->shouldBeCalled();
        $association->setOwner(null)->shouldBeCalled();

        $this->addAssociation($association);
        $this->removeAssociation($association);

        $this->hasAssociation($association)->shouldReturn(false);
    }
}


text:
namespace ash {

class MultiDeviceSetupScreenView;

namespace multidevice_setup {
class MultiDeviceSetupClient;
}

class MultiDeviceSetupScreen : public BaseScreen {
 public:
  enum class Result { NEXT, NOT_APPLICABLE };

  static std::string GetResultString(Result result);

  using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
  MultiDeviceSetupScreen(base::WeakPtr<MultiDeviceSetupScreenView> view,
                         const ScreenExitCallback& exit_callback);

  MultiDeviceSetupScreen(const MultiDeviceSetupScreen&) = delete;
  MultiDeviceSetupScreen& operator=(const MultiDeviceSetupScreen&) = delete;

  ~MultiDeviceSetupScreen() override;

  void AddExitCallbackForTesting(const ScreenExitCallback& testing_callback) {
    exit_callback_ = base::BindRepeating(
        [](const ScreenExitCallback& original_callback,
           const ScreenExitCallback& testing_callback, Result result) {
          original_callback.Run(result);
          testing_callback.Run(result);
        },
        exit_callback_, testing_callback);
  }

  void set_multidevice_setup_client_for_testing(
      multidevice_setup::MultiDeviceSetupClient* client) {
    setup_client_ = client;
  }

 protected:
  // BaseScreen:
  bool MaybeSkip(WizardContext& context) override;
  void ShowImpl() override;
  void HideImpl() override;
  void OnUserAction(const base::Value::List& args) override;

 private:
  friend class MultiDeviceSetupScreenTest;

  // This enum is tied directly to a UMA enum defined in
  // //tools/metrics/histograms/enums.xml, and should always reflect it (do not
  // change one without changing the other).  Entries should be never modified
  // or deleted.  Only additions possible.
  enum class MultiDeviceSetupOOBEUserChoice {
    kAccepted = 0,
    kDeclined = 1,
    kMaxValue = kDeclined
  };

  // Inits `setup_client_` if it was not initialized before.
  void TryInitSetupClient();

  static void RecordMultiDeviceSetupOOBEUserChoiceHistogram(
      MultiDeviceSetupOOBEUserChoice value);

  multidevice_setup::MultiDeviceSetupClient* setup_client_ = nullptr;

  base::WeakPtr<MultiDeviceSetupScreenView> view_;
  ScreenExitCallback exit_callback_;
};

}  // namespace ash

#endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_MULTIDEVICE_SETUP_SCREEN_H_


text:
using System;
using System.Threading.Tasks;
using Tampleworks.WindowsApplicationBlock.ApplicationLogicAbstractions;
using Windows.ApplicationModel.ExtendedExecution;

namespace Tampleworks.WindowsApplicationBlock.ApplicationLogicEnvironment
{
    /// <summary>
    /// Provides extended execution session for applicaiton logic.
    /// </summary>
    internal sealed class ExtendedExecutionSessionFactory : IExtendedExecutionSessionFactory
    {
        public ExtendedExecutionSessionFactory() { }

        public async Task<IDisposable> TryRequestAsync(
            string description, Action revoked
        )
        {
            var session = new ExtendedExecutionSession();
            session.Reason = ExtendedExecutionReason.Unspecified;
            session.Description = description;
            session.Revoked += (sender, e) => revoked();
            ExtendedExecutionResult result = await session.RequestExtensionAsync();
            switch (result)
            {
                case ExtendedExecutionResult.Allowed: return session;
                case ExtendedExecutionResult.Denied:
                    session.Dispose();
                    return null;
                default: throw new NotSupportedException();
            }
        }
    }
}


text:
<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\Url;
use kartik\file\FileInput;

/* @var $this yii\web\View */
/* @var $model common\models\WechatBadge */
/* @var $form yii\widgets\ActiveForm */
?>

    <?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>

	<?php

        echo $form->field($model, 'file1')->widget(FileInput::classname(), [
            'options' => ['accept' => 'image/*'],
            'pluginOptions' => [
                'initialPreview'=>[
                    $model->lighten ? Url::to(["/file", "id" => $model->lighten]) : null,
                ],
                'initialPreviewAsData'=>true,
                'showUpload' => false,
                'maxFileSize' => 2048
            ]
        ]);

        echo $form->field($model, 'file2')->widget(FileInput::classname(), [
            'options' => ['accept' => 'image/*'],
            'pluginOptions' => [
                'initialPreview'=>[
                    $model->lighten ? Url::to(["/file", "id" => $model->dim]) : null,
                ],
                'initialPreviewAsData'=>true,
                'showUpload' => false,
                'maxFileSize' => 2048
            ]
        ]);

    ?>
    <?= $form->field($model, 'lighten')->hiddenInput()->label(false) ?>

    <?= $form->field($model, 'dim')->hiddenInput()->label(false) ?>

    <?= $form->field($model, 'type')->dropDownList([ 'step' => '步数', 'continue' => '持续性', 'distance' => '距离', 'time' => '时间', ], ['prompt' => '']) ?>

    <?= $form->field($model, 'desc_content')->textarea(['maxlength' => true]) ?>

    <?= $form->field($model, 'award')->textInput() ?>

    <?= $form->field($model, 'is_repeat')->dropDownList([ '0' => '否', '1' => '是', ], ['prompt' => '']) ?>

        <?= Html::submitButton($model->isNewRecord ? Yii::t('backend-wechatbadge', 'Create') : Yii::t('backend-wechatbadge', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

    <?php ActiveForm::end(); ?>