async def put_body_chunk(self, chunk): ASSERT.true(self._has_begun) ASSERT.is_not(self._send_mechanism, _SendMechanisms.SENDFILE) self._send_mechanism = _SendMechanisms.SEND await self._headers_sent.wait() if chunk: await self._send_all(chunk)
def set_(tables, *, revision, key, value): ASSERT.greater_or_equal(revision, 0) ASSERT.true(key) ivs = {'revision': revision + 1, 'key': key, 'value': value} return [ sqlite.upsert(tables.keyspace).values(**ivs), tables.revisions.insert().values(**ivs), ]
async def sendfile(self, file): ASSERT.true(self._has_begun) # sendfile can be called only once. ASSERT.is_(self._send_mechanism, _SendMechanisms.UNDECIDED) ASSERT.not_none(file) self._send_mechanism = _SendMechanisms.SENDFILE await self._headers_sent.wait() with timers.timeout_after(self._SENDFILE_TIMEOUT): return await self._sock.sendfile(file)
def get(self): """Read parameter value. For the ease of writing correct code, a parameter becomes immutable once it is read. """ ASSERT.true(INITIALIZED) self._have_been_read = True return self._value
def next_key(key): ASSERT.true(key) bs = [] carry = 1 for b in reversed(key): b += carry if b > 0xff: bs.append(0) else: bs.append(b) carry = 0 if carry: bs.append(1) bs.reverse() return bytes(bs)
def reset(self): """Reset response status, headers, and content.""" ASSERT.true(self.is_uncommitted()) self._status = consts.Statuses.OK # Do NOT call `self.headers.clear`, but replace it with a new # headers object instead because application code might still # keep a reference to the old headers object, and clearing it # could cause confusing results. self.headers = self.Headers(self.is_uncommitted) # It is safe to replace `_precommit` on uncommitted response. self._precommit.close() self._precommit = self._make_precommit()
async def join(self): if self.__future.is_completed(): return # Since the callback could be fired from another thread, which # may not have the right kernel object in its context, we should # get the right kernel object from the context here, and pass it # to the callback function. kernel = contexts.get_kernel() callback = lambda: kernel.unblock(self.__future) await traps.block( self.__future, lambda: self.__future. add_callback(lambda _: kernel.post_callback(callback)), ) ASSERT.true(self.__future.is_completed())
def cmd_remove( *, image_id=None, name=None, version=None, tag=None, skip_active=False ): """Remove an image, or no-op if image does not exist.""" oses.assert_root_privilege() with locks.acquiring_exclusive(_get_tags_path()), \ locks.acquiring_exclusive(get_trees_path()): image_dir_path = _find_image_dir_path(image_id, name, version, tag) if image_dir_path: ASSERT.true(_maybe_remove_image_dir(image_dir_path) or skip_active) else: LOG.debug( 'image does not exist: image_id=%s, nv=%s:%s, tag=%s', image_id, name, version, tag )
def get(tables, *, key, revision=0): ASSERT.true(key) if revision == 0: table = tables.keyspace return ( select([table.c.revision, table.c.key, table.c.value])\ .where(table.c.key == key) ) else: table = tables.revisions return ( select([table.c.revision, table.c.key, table.c.value])\ .where(table.c.revision <= revision) .where(table.c.key == key) .order_by(table.c.revision.desc()) )
def cmd_export_overlay(pod_id, output_path, filter_patterns, *, debug=False): oses.assert_root_privilege() ASSERT.not_predicate(output_path, g1.files.lexists) # Exclude pod-generated files. # TODO: Right now we hard-code the list, but this is fragile. filter_args = [ '--exclude=/etc/machine-id', '--exclude=/var/lib/dbus/machine-id', '--exclude=/etc/hostname', '--exclude=/etc/hosts', '--exclude=/etc/systemd', '--exclude=/etc/.pwd.lock', '--exclude=/etc/mtab', # Remove distro unit files. '--exclude=/etc/systemd/system', '--exclude=/lib/systemd/system', '--exclude=/usr/lib/systemd/system', ] filter_args.extend('--%s=%s' % pair for pair in filter_patterns) if debug: # Log which files are included/excluded due to filter rules. filter_args.append('--debug=FILTER2') with locks.acquiring_exclusive(_get_active_path()): pod_dir_path = ASSERT.predicate(_get_pod_dir_path(pod_id), Path.is_dir) pod_dir_lock = ASSERT.true(locks.try_acquire_exclusive(pod_dir_path)) try: upper_path = _get_upper_path(pod_dir_path) bases.rsync_copy(upper_path, output_path, filter_args) finally: pod_dir_lock.release() pod_dir_lock.close()
def init(self, index, size=None): if not 0 <= index < len(self): raise IndexError(index) if self.schema.element_type.is_list(): ASSERT.greater_or_equal(size, 0) return DynamicListBuilder( self._message, self.schema.element_type.as_list(), self._raw.init(index, size).asDynamicList(), ) else: # Although Builder::init does not support struct type, to # make interface consistent between list-of-struct and # struct-of-struct, let's return something here rather than # erring out. ASSERT.true(self.schema.element_type.is_struct()) return self[index]
async def wait(self): """Wait until notified. To be somehow compatible with ``threading.Condition.wait``, this always return true (since it never times out). """ ASSERT.true(self._lock.is_owner()) waiter = Gate() self._waiters.add(waiter) # NOTE: We have not implemented ``RLock`` yet, but when we do, # be careful **NOT** to call ``release`` here, since you cannot # unlock the lock acquired recursively. self._lock.release() try: await waiter.wait() finally: await self._lock.acquire() return True
def tick(self, trap_result, trap_exception): """Run coroutine through the next trap point. NOTE: ``tick`` catches ``BaseException`` raised from the coroutine. As a result, ``SystemExit`` does not bubble up to the kernel event loop. I believe this behavior is similar to Python threading library and thus more expected (``SystemExit`` raised in non- main thread does not cause CPython process to exit). If you want raising ``SystemExit`` in a task to be effective, you have to call ``Task.get_result_nonblocking`` in the main thread (or implicitly through ``Kernel.run``). """ ASSERT.false(self._completed) if trap_exception: trap = self._tick(self._coroutine.throw, trap_exception) else: trap = self._tick(self._coroutine.send, trap_result) if trap is not None: return trap ASSERT.true(self._completed) self._call_callbacks() return None
def _run_one_ready_task(self): task, trap_result, trap_exception = self._ready_tasks.popleft() override = self._to_raise.pop(task, None) if override is not None: trap_result = None trap_exception = override self._current_task = task try: trap = task.tick(trap_result, trap_exception) finally: self._current_task = None if trap is None: ASSERT.true(task.is_completed()) self._trap_return(self._task_completion_blocker, task) # Clear disrupter. self._to_raise.pop(task, None) self._timeout_after_blocker.cancel(task) self._num_tasks -= 1 return task ASSERT.false(task.is_completed()) override = self._to_raise.pop(task, None) if override: self._ready_tasks.append(TaskReady(task, None, override)) else: handler = self._blocking_trap_handlers[trap.kind] try: handler(task, trap) except Exception as exc: self._ready_tasks.append(TaskReady(task, None, exc)) return None
def get_result_nonblocking(self): ASSERT.true(self.is_completed()) self._joined = True if self._exception: raise self._exception return self._result
def _call_callbacks(self): ASSERT.true(self._completed) callbacks, self._callbacks = self._callbacks, None for callback in callbacks: self._call_callback(callback)
def get_exception_nonblocking(self): ASSERT.true(self.is_completed()) self._joined = True return self._exception
def status(self): # It is unsafe to read status before the context is committed. ASSERT.true(self._is_committed) return ASSERT.not_none(self._status)
def headers(self): # It is unsafe to read headers before the context is committed. ASSERT.true(self._is_committed) return self._headers
def notify(self, n=1): ASSERT.true(self._lock.is_owner()) for _ in range(min(n, len(self._waiters))): self._waiters.pop().unblock()
def status(self, status): ASSERT.true(self.is_uncommitted()) self._status = _cast_status(status)
def text(self): ASSERT.true(self._raw.isText()) return str(self._raw.getText(), 'utf-8')
def __delitem__(self, header): ASSERT.true(self._is_uncommitted()) del self._headers[header]
def __setitem__(self, header, value): ASSERT.true(self._is_uncommitted()) ASSERT.isinstance(header, str) ASSERT.isinstance(value, str) self._headers[header] = value
def chown_app(path): """Change owner to root and group to the application group.""" shutil.chown(path, 'root', ASSERT.true(PARAMS.application_group.get()))
def __post_init__(self): ASSERT.true(self.webhook)
def release(self): ASSERT.true(self.is_owner()) self._locked = False contexts.get_kernel().unblock(self)
def assert_keyed(self): ASSERT.true(self.is_keyed(), message='expect keyed schema')
def flush(self): ASSERT.true(self.eof) ASSERT.equal(self._chunk_remaining, -2) return []
def end(self): ASSERT.true(self._has_begun) ASSERT.true(self._headers_sent.is_set()) self._has_begun = False self._headers_sent.clear() self._send_mechanism = _SendMechanisms.UNDECIDED