text:
gitserve
=========

A restricted SSH server and library for supporting controlled Git repository
access and code submission.

This library comes with two tools:
 * `git-submitd`: A service that supports one-way pushes of full repos, along
      with submission hooks for inspecting and accepting those repos.
 * `git-hostd`: A service that hosts a git repo or a folder of git repos to
      users that (optionally) have ssh keys in a specific whitelist.

### git-hostd sample interaction

Make a repo and start the server:
```shell
~$ go get github.com/jtolds/gitserve/cmd/git-hostd
~$ mkdir -p myrepo && cd myrepo
~/myrepo$ git init
Initialized empty Git repository in /home/jt/myrepo/.git/
~/myrepo$ touch newfile1
~/myrepo$ git add .
~/myrepo$ git commit -m 'first commit!'
[master (root-commit) 2266e76] first commit!
 0 files changed
 create mode 100644 newfile1
~/myrepo$ git hostd
2014/08/16 02:11:07 NOTE - listening on [::]:7022
```

Clone your repo from somewhere else, make a change, and push:
```shell
~$ git clone ssh://localhost:7022/ myrepo2
Cloning into 'myrepo2'...
Welcome to the gitserve git-hostd code hosting tool!
Please see https://github.com/jtolds/gitserve for more info.

remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
~$ cd myrepo2
~/myrepo2$ touch newfile2
~/myrepo2$ git add newfile2
~/myrepo2$ git commit -m 'second commit!'
[master 043fcab] second commit!
 0 files changed
 create mode 100644 newfile2
~/myrepo2$ git push origin HEAD:refs/heads/mybranch
Welcome to the gitserve git-hostd code hosting tool!
Please see https://github.com/jtolds/gitserve for more info.

Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 230 bytes, done.

Please see https://github.com/jtolds/gitserve for more info.

Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 218 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)

Thanks for pushing some code!
===============================================================
You are user: jt
You pushed repo: /tmp/submission-907291030
You came from: [::1]:39059
The repo name is: /myrepo
Your public key is: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDB...

You pushed:
/tmp/tmpRM4PbC
/tmp/tmpRM4PbC/newfile1
/tmp/tmpRM4PbC/newfile2

To ssh://localhost:7022/myrepo
 * [new branch]      master -> master
~/myrepo$
```

Make sure to check out `submission-trigger.py` to see how to customize
git-submitd for your own ends!

#### License

```plain
The MIT License (MIT)

Copyright (c) 2014 JT Olds

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

 IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

repository: minurc/gitserve

repo_name: minurc/gitserve


text:
# PyPress

Tools and example code to read a Facebook data export and insert bits of it into Wordpress

Includes code to

- Parse the Facebook JSON dump
- Scrape websites for titles
- Look up YouTube videos for titles
- Post to Wordpress

Completely unsupported, poorly documented and free for you to play with!

This is not a tool you can just use, it's bits of code to cut and paste together to make your own tool.

See blog post at this url for more information

https://ncot.uk/compsci/import-facebook-into-wordpress/

license: MIT

repository: ncot-technology/PyPress

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: ncot-technology/PyPress


text:
# Flutter - Shrine App

## About

This is the final version of the app featured in Flutter's Material codelabs and presented at Google I/O '18.

You can find an enhanced version prvided by the Flutter team here:
(https://github.com/flutter/samples/tree/master/shrine).

iOS:

![](https://media.giphy.com/media/YkXMoKQykAFjxTPsfP/giphy.gif)

Android:

![](https://media.giphy.com/media/k7ZJd0ouua7iYtQ5Sh/giphy.gif)

Followed these codelabs from Google from start to finish:

* [https://codelabs.developers.google.com/codelabs/mdc-101-flutter](https://codelabs.developers.google.com/codelabs/mdc-101-flutter)
* [https://codelabs.developers.google.com/codelabs/mdc-102-flutter](https://codelabs.developers.google.com/codelabs/mdc-102-flutter)
* [https://codelabs.developers.google.com/codelabs/mdc-103-flutter](https://codelabs.developers.google.com/codelabs/mdc-103-flutter)
* [https://codelabs.developers.google.com/codelabs/mdc-104-flutter](https://codelabs.developers.google.com/codelabs/mdc-104-flutter)

Highly recommended if you're just starting out with Flutter.

Flutter docs [here](https://flutter.io).


text:
---
layout: example
title: Line Chart Example
permalink: /examples/line-chart/index.html
spec: line-chart
image: /examples/img/line-chart.png
---

Line charts are used to depict changing values, with line slopes conveying rates of change. Different interpolators change the curvature of the line. Options such as [cardinal](https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Cardinal_spline) or [Catmull-Rom](https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline) interpolation can produce pleasing curves, but can also "hallucinate" maximum or minimum values that do not exist in the data. Use [monotone interpolation](https://en.wikipedia.org/wiki/Monotone_cubic_interpolation) for smooth curves that faithfully preserve monotonicity.

{% include example spec=page.spec %}

repository: vega/vega

branch_name: refs/heads/main

gha_language: JavaScript

repo_name: vega/vega


text:
# Inhabited subtypes

```agda
module foundation.inhabited-subtypes where
```

<details><summary>Imports</summary>

```agda
open import foundation.dependent-pair-types
open import foundation.inhabited-types
open import foundation.propositional-truncations
open import foundation.subtype-identity-principle
open import foundation.subtypes
open import foundation.universe-levels

open import foundation-core.contractible-types
open import foundation-core.equivalences
open import foundation-core.identity-types
open import foundation-core.propositions
```

</details>

## Idea

An inhabited subtype of a type `A` is a subtype `P` of `A` such that the
underlying type of `P` is inhabited.

```agda
is-inhabited-subtype-Prop :
  {l1 l2 : Level} {A : UU l1} → subtype l2 A → Prop (l1 ⊔ l2)
is-inhabited-subtype-Prop P = is-inhabited-Prop (type-subtype P)

is-inhabited-subtype :
  {l1 l2 : Level} {A : UU l1} → subtype l2 A → UU (l1 ⊔ l2)
is-inhabited-subtype P = type-Prop (is-inhabited-subtype-Prop P)

inhabited-subtype :
  {l1 : Level} (l2 : Level) → UU l1 → UU (l1 ⊔ lsuc l2)
inhabited-subtype l2 A = type-subtype (is-inhabited-subtype-Prop {l2 = l2} {A})

module _
  {l1 l2 : Level} {A : UU l1} (P : inhabited-subtype l2 A)
  where

  subtype-inhabited-subtype : subtype l2 A
  subtype-inhabited-subtype = pr1 P

  is-inhabited-subtype-inhabited-subtype :
    is-inhabited-subtype subtype-inhabited-subtype
  is-inhabited-subtype-inhabited-subtype = pr2 P

  type-inhabited-subtype : UU (l1 ⊔ l2)
  type-inhabited-subtype = type-subtype subtype-inhabited-subtype

  inhabited-type-inhabited-subtype : Inhabited-Type (l1 ⊔ l2)
  pr1 inhabited-type-inhabited-subtype = type-inhabited-subtype
  pr2 inhabited-type-inhabited-subtype =
    is-inhabited-subtype-inhabited-subtype

  is-in-inhabited-subtype : A → UU l2
  is-in-inhabited-subtype = is-in-subtype subtype-inhabited-subtype

  is-prop-is-in-inhabited-subtype :
    (x : A) → is-prop (is-in-inhabited-subtype x)
  is-prop-is-in-inhabited-subtype =
    is-prop-is-in-subtype subtype-inhabited-subtype

  inclusion-inhabited-subtype : type-inhabited-subtype → A
  inclusion-inhabited-subtype = inclusion-subtype subtype-inhabited-subtype

  ap-inclusion-inhabited-subtype :
    (x y : type-inhabited-subtype) →
    x ＝ y → (inclusion-inhabited-subtype x ＝ inclusion-inhabited-subtype y)
  ap-inclusion-inhabited-subtype =
    ap-inclusion-subtype subtype-inhabited-subtype

  is-in-inhabited-subtype-inclusion-inhabited-subtype :
    (x : type-inhabited-subtype) →
    is-in-inhabited-subtype (inclusion-inhabited-subtype x)
  is-in-inhabited-subtype-inclusion-inhabited-subtype =
    is-in-subtype-inclusion-subtype subtype-inhabited-subtype
```

## Properties

### Characterization of equality of inhabited subtypes

```agda
has-same-elements-inhabited-subtype-Prop :
  {l1 l2 l3 : Level} {A : UU l1} →
  inhabited-subtype l2 A → inhabited-subtype l3 A → Prop (l1 ⊔ l2 ⊔ l3)
has-same-elements-inhabited-subtype-Prop P Q =
  has-same-elements-subtype-Prop
    ( subtype-inhabited-subtype P)
    ( subtype-inhabited-subtype Q)

has-same-elements-inhabited-subtype :
  {l1 l2 l3 : Level} {A : UU l1} →
  inhabited-subtype l2 A → inhabited-subtype l3 A → UU (l1 ⊔ l2 ⊔ l3)
has-same-elements-inhabited-subtype P Q =
  type-Prop (has-same-elements-inhabited-subtype-Prop P Q)

is-prop-has-same-elements-inhabited-subtype :
  {l1 l2 l3 : Level} {A : UU l1} →
  (P : inhabited-subtype l2 A) (Q : inhabited-subtype l3 A) →
  is-prop (has-same-elements-inhabited-subtype P Q)
is-prop-has-same-elements-inhabited-subtype P Q =
  is-prop-type-Prop (has-same-elements-inhabited-subtype-Prop P Q)

module _
  {l1 l2 : Level} {A : UU l1} (P : inhabited-subtype l2 A)
  where

  refl-has-same-elements-inhabited-subtype :
    has-same-elements-inhabited-subtype P P
  refl-has-same-elements-inhabited-subtype =
    refl-has-same-elements-subtype (subtype-inhabited-subtype P)

  is-contr-total-has-same-elements-inhabited-subtype :
    is-contr
      ( Σ (inhabited-subtype l2 A) (has-same-elements-inhabited-subtype P))
  is-contr-total-has-same-elements-inhabited-subtype =
    is-contr-total-Eq-subtype
      ( is-contr-total-has-same-elements-subtype
        ( subtype-inhabited-subtype P))
      ( λ Q → is-prop-type-trunc-Prop)
      ( subtype-inhabited-subtype P)
      ( refl-has-same-elements-inhabited-subtype)
      ( is-inhabited-subtype-inhabited-subtype P)

  extensionality-inhabited-subtype :
    (Q : inhabited-subtype l2 A) → (P ＝ Q) ≃
    has-same-elements-inhabited-subtype P Q
  extensionality-inhabited-subtype Q =
    ( extensionality-subtype
      ( subtype-inhabited-subtype P)
      ( subtype-inhabited-subtype Q)) ∘e
    ( extensionality-type-subtype' is-inhabited-subtype-Prop P Q)

  has-same-elements-eq-inhabited-subtype :
    (Q : inhabited-subtype l2 A) →
    (P ＝ Q) → has-same-elements-inhabited-subtype P Q
  has-same-elements-eq-inhabited-subtype Q =
    map-equiv (extensionality-inhabited-subtype Q)

  eq-has-same-elements-inhabited-subtype :
    (Q : inhabited-subtype l2 A) →
    has-same-elements-inhabited-subtype P Q → P ＝ Q
  eq-has-same-elements-inhabited-subtype Q =
    map-inv-equiv (extensionality-inhabited-subtype Q)

  refl-extensionality-inhabited-subtype :
    map-equiv (extensionality-inhabited-subtype P) refl ＝
    refl-has-same-elements-inhabited-subtype
  refl-extensionality-inhabited-subtype = refl
```

repository: UniMath/agda-unimath

gha_language: Agda

gha_license_id: MIT

repo_name: UniMath/agda-unimath


text:
# Iterative solvers for cell-based EMI models

This repository contains source codes and an environment used to produce
results of the chapter in the EMI book **EMI: CELL BASED MATHEMATICAL MODEL OF EXCITABLE CELLS**
concerning iterative solvers.

## Installation
### Obtaining the image
The environment is provided as a docker container built on top of FEniCS
2017.2.0 (which uses Python 2). The container can be built locally by

```
docker build --no-cache -t emi_book_solvers .
```
from the root directory of this repository. You would then run the container
as

```
docker run -it -v $(pwd):/home/fenics/shared emi_book_solvers
```

Alternatively, pull and run the image built in the cloud

```
docker run -it -v $(pwd):/home/fenics/shared mirok/emi-book-solvers
```

### Testing
Having lauched the container navigate to the source folder and launch
the test shell script

```
# You are inside docker shell
# fenics@268200ea18c2:~$ pwd
# /home/fenics

cd emi-book-solvers
cd emi
sh test.sh
```

If `You are all set message appears` everything is good to go.

## Monolithic solver experiments
Results of the chapter can be obtained by running convergence studies of
the different formulations. Below the single-dimensional primal formulation
is used. Boundedness of the Krylov iterations using different preconditioners
and different material parameters in the formulation can be tested with

```
fenics@3fb6d19d16c1:~/emi-book-solvers/emi$ python check_iters.py fem/prime_single.py -ncases 4 \
-param_eps 0.01 -param_kappa 1 -ksp_type cg -ksp_rtol 1E-10 -precond 2
```

Here 4 refinements, conductivity value 1, and time step parameter 0.01 are used. In addition,
the iterative solver is set to conjugate gradients (CG) using relative tolerance of
1E-10 and preconditioner corresponding to key 2 in the `W_RIESZ_MAPS` of
`prime_single.py` [module](https://github.com/MiroK/emi-book-solvers/blob/master/emi/fem/prime_single.py#L231).
Note that the single-dimensional formulation is the only one of the 4 discussed which results in
positive symmetric matrix. The other formulations lead to saddle point systems and as such, they
should be solved with `-ksp_type minres` (Minimal Residual method) or other suitable solvers from [PETSc](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/KSP/KSPType.html).
A succesfull run of `check_iters.py` results in a result file `iters_fem.prime_single_monolithic_precond_standard_kappa1_eps0.01.txt`
(since the key 2 preconditioner is named __monolithic__, cf. the source code), which is
located in `/home/fenics/emi-book-solvers/emi/results`. The file contains details of
the refinement study in particular the columns of the number of unknowns (ndofs), different errors
as specified in the `setup_error_monitor` function of the tested formulation script.
Important for the boundedness, the number of Krylov iterations is specified in the
`niters` column. Columns `dt`, `Bdt` and `total` contain the run time of the Krylov
loop, setup of the preconditioner and total time spent solving the system respecively.

```
# ('plot', 0), ('ncases', 4), ('-ksp_monitor_true_residual', 'none'), ('run_mms', 1), ('-ksp_max_it', 1500), ('-ksp_type', 'cg'), ('precond', 2), ('-ksp_rtol', '1E-10'), ('save_dir', './results'), ('case0', 2), ('problem', 'fem/prime_single.py'), ('-ksp_atol', 1e-20), ('norm', 'standard')
# kappa1_eps0.01
# l ndofs h e[|u|_1] r[|u|_1] e[|u|_0] r[|u|_0] niters dt Bdt total |r|_2 cond dimW_0 dimW_1
```

Condition numbers of the preconditioned problems are tested by running
```
fenics@3fb6d19d16c1:~/emi-book-solvers/emi$ python check_eigs.py fem/prime_single.py -ncases 4 \
-param_eps 0.01 -param_kappa 1 -precond 2
```

The script stores the simulation output in the file `eigs_fem.prime_single_monolithic_inner_product_kappa1_eps0.01.txt`
which resides in `/home/fenics/emi-book-solvers/emi/results`. The file's content is as follows

```
fenics@3fb6d19d16c1:~/emi-book-solvers/emi$ cat results/eigs_fem.prime_single_monolithic_inner_product_kappa1_eps0.01.txt
# ('-st_ksp_rtol', 1e-08), ('-eps_monitor', 'none'), ('ncases', 4), ('-eps_max_it', 20000), ('-eps_type', 'krylovschur'), ('-eps_nev', 3), ('-ksp_type', 'cg'), ('precond', 2), ('-st_ksp_monitor_true_residual', 'none'), ('save_dir', './results'), ('alpha', [1.0]), ('problem', 'fem/prime_single.py'), ('-ksp_rtol', '1E-10'), ('-eps_tol', 0.001)
# kappa1_eps0.01
33 0.353553 1.0000000000000300 direct
97 0.176777 1.0000000000000338 direct
321 0.0883883 1.0000000000000386 direct
1153 0.0441942 1.0000000000001226 direct
```

We can indeed see that preconditioning the system $Ax=b$ with $A^{-1}$ results in unit
condition number, cf. the third column.

## Domain decomposition solver experiments
Results concerning Robin-Neumann domain decomposition solver can be reproduced by

```
fenics@3fb6d19d16c1:~/emi-book-solvers/emi$ python check_sanity.py fem/DD.py -ncases 4 -param_eps 1 -param_kappa 1 -param_tol 1E-3
```

Here the switch `-param_tol` specifies the convergence tolerance for the algorithm.
For each mesh resolution a file `emi_DD_n$N_tol0.001_eps1.txt` is produced (above, corresponding
to 4 refinements `N` would take values 4, 8, 16, 32) which contains the convergence
history. Therefore, the final iteration counts can be extracted from the file. Run
time of the solver can be found in the file `sanity_fem.DD_standard_kappa1_eps1_tol0.001.txt`
under column `total`. As before, the file is located in the result folter.

## Troubleshooting
Please use the GitHub issue tracker for reporting issues, discussing code
contributions or requesting assistance.

## Citing
This code is based on several other packages in addition to [FEniCS](https://fenicsproject.org/citing/).

1. [**FEniCS_ii**](https://github.com/MiroK/fenics_ii) is used to perform assembly of the multiscale varitional forms
2. [**cbc.block**](https://bitbucket.org/fenics-apps/cbc.block/src/master/) is used to represent the discrete operators
3. [**hsmg**](https://github.com/MiroK/hsmg) provides fractional Laplacian preconditioners

These can be cited as

1. _Kuchta, Miroslav. "Assembly of multiscale linear PDE operators." arXiv preprint arXiv:1912.09319 (2019)._
2. _Mardal, Kent-Andre, and Joachim Berdal Haga. "Block preconditioning of systems of PDEs." Automated solution of differential equations by the finite element method. Springer, Berlin, Heidelberg, 2012. 643-655._
3a. _Bærland, Trygve, Miroslav Kuchta, and Kent-Andre Mardal. "Multigrid methods for discrete fractional sobolev spaces." SIAM Journal on Scientific Computing 41.2 (2019): A948-A972.
3b. _Kuchta, Miroslav, et al. "Preconditioners for saddle point systems with trace constraints coupling 2d and 1d domains." SIAM Journal on Scientific Computing 38.6 (2016): B962-B987._

repository: MiroK/emi-book-solvers

repo_name: MiroK/emi-book-solvers


text:
# FedDebug: Systematic Debugging for Federated Learning Applications

*Waris Gill, Ali Anwar, and Muhammad Ali Gulzar. Feddebug: Systematic debugging for federated learning applications. In Proceedings of the 45th International Conference on Software Engineering (ICSE '23). Association for Computing Machinery, New York, NY, USA.*

The ArXiv version of the manuscript is avaibable at : [FedDebug](https://arxiv.org/abs/2301.03553)

FedDebug enables interactive and automated fault localization in Federation Learning (FL) applications. It adapts conventional debugging practices in FL with its breakpoint and fix & replay featur and it offers a novel differential testing technique to automatically identify the precise faulty clients.FedDebug tool artifact comprises a two-step process
  - Interactive Debugging Constructs integrated with IBMFL framework via **FL simulation in a Docker Image**
  - Automated Faulty Client Localization  via **Google Colab Notebooks**

# 1. Interactive debugging of FL Applications in IBMFL with FedDebug
FedDebug's interactive debugging module takes inspiration from traditional debuggers, such as gdb, and enables real-time interactive debugging on a simulation of a live FL application.

Below, we provide step-by-step walkthrough of FedDebug's interactive debugging features in IBMFL. For ease of installation, we offer pre-configured *Docker Image* of FedDebug enabled IBMFL.

## Step 1.1: Build FedDebug's Docker Image and Initiate
Please type `"docker build -t ibmfl ."`.  It will build docker form the `Dockerfile`. To run and interact with `ibmfl` docker type the following command `docker run -it ibmfl`. It will start the docker and now you can interact with it. Type `ls` in the docker shell to display the current directory content to check whether everything is installed correctly.  You can check more about dockers on the following link [Docker Tutorial](https://docs.docker.com/get-started/).

![docker](figures/docker.png)

### Tmux Tutorial
In this tutorial, we will be using Tmux to simulate a distributed FL environment in Docker, representing both FL clients and aggregator. Tmux is a terminal multiplexer that allows you to split your terminal screen horizontally. Tmux allows us to interact with the client and aggregator side of IBMFL and seemlesly move between those two interfaces. To start tmux, simply type '`tmux`' in the terminal. You can check more about `tmux` on this link [Tmux Quick Tutorial](https://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/).

### Splitting Screen in Tmux
To split the screen horizontally, type in a tmux session ` Ctrl + b + " `. It will split the screen into two terminals.

![tmux image](figures/tmux1.png)

You can move between terminals (panes) by pressing `Ctrl + b` followed by the `up` and `down` arrows keys.

## Step 1.2: Running the Aggregator in FedDebug enabled IBMFL
In one of the tmux terminals, type `python sim_agg.py` to run the aggregator.
![agg start](figures/python_sim_agg_py.png)

After running this command, you will see the following output: "Press key to continue." Right now, ***do not press any key*** and move to another tmux terminal.

![agg start](figures/agg_start_output.png)

## Step 1.3: Running the Parties/Clients in FedDebug enabled IBMFL
In the second terminal, type `python sim_party.py`. This will start the ten parties and connect them to the second aggregator.
![agg start](figures/python_sim_party.png)
After running this command, you will see the following output:
![parties connected](figures/parties_connected.png)

## Step 1.4: Starting the Training
Move back to the aggregator terminal and press `enter key`. This will start the training from the aggregator for `10 rounds with 10 clients`.  Currently, breakpoint is set at round 5, so the terminal will stop displaying logs after `round 5` and you will see the following output:

![breakpoint](figures/breapoint.png).

***Note: you can change the `breakpoint` round id in `sim_agg.py`***

## Step 1.5: FedDebug Interactive Debugging Constructs

**`help:`** You can type `help` to see all the commands available at the round level in the debugger.

![round help](figures/round-help.png)

**`ls:`** The `ls` command at the round level will display generic information about the round.

![ls round](figures/ls.png)

**`step next, step back, and step in:`** You can also use the `step next`, `step back`, and  `step in` commands to navigate through the rounds.

![step next-back](figures/step-next-in-back.png)

## Step 1.6: Navigating inside a Round with FedDebug

After `step in` you can also type `help` to see the commands available inside a round.

![client help command](figures/client-help.png)

**`ls:`** You can use the `ls`  command inside a round to display all the clients in the round with their accuracies.

**`agg:`** Similarly can also use the `agg` to partially aggregate the models from a subset of clients for the partial evaluation to inspect their performance.

**Note: We have replace `step in` command inside the round with `agg` to avoid any confusion with  `step in` command of  rounds.**

![ls and agg commands](figures/client-ls-agg.png)

**`step out:`** To leave a round, you can also use the `step out` command to step out of a round.
![step out command](figures/step-out.png)

## Step 1.7: Removing a Client with FedDebug

**`remove client <client id>:`** Suppose that you identify a faulty client in `round 8`, you can remove its contribution from the round using the `remove client <client id>` command.

![remove client command](figures/remove-client.png)

This will resume the training from `round 9` instead of `round 5`, and the faulty client will not be included from `round 8`.

![Result of remove client command](figures/remove-client-result.png)

**Note: After removing the client, the training is complete. **

## Step 1.8: Resume after a debugging session

To check the functionality of  `resume` command, restart the aggregator (`python sim_agg.py`) and clients ((`python sim_party.py`))  as explained above. Perform some actions (e.g., `step in, step out, ls` etc ), except  `remove client`. Suppose that there is no faulty client and you want resume the training without any further debugging. You can type `resume` to resume training and you will see that the aggregator immediately displays the the output of all the rounds without any retraining.

![resume](figures/resume.png).

# 2. Automated faulty Client Localization with FedDebug.

WARIS : TODO HEre
GIVe colab link and show steps
## Step  2.1
## Step 2.2 etc.

repository: SEED-VT/FedDebug

filename: README copy.md

repo_name: SEED-VT/FedDebug


text:
# Metrics

__prefix__: `/grafanalabs/cadvisor/container/<namespace>/<podname>/<container_name>`

| Name                             |
|----------------------------------|
| `cpu/load`                       |
| `cpu/system/usage`               |
| `cpu/total/usage`                |
| `cpu/user/usage`                 |
| `fs/baseUsage`                   |
| `fs/inodeUsage`                  |
| `fs/totalUsage`                  |
| `iface/<device_name>/rx_bytes`   |
| `iface/<device_name>/rx_dropped` |
| `iface/<device_name>/rx_errors`  |
| `iface/<device_name>/rx_packets` |
| `iface/<device_name>/tx_bytes`   |
| `iface/<device_name>/tx_dropped` |
| `iface/<device_name>/tx_errors`  |
| `iface/<device_name>/tx_packets` |
| `mem/cache`                      |
| `mem/failcnt`                    |
| `mem/rss`                        |
| `mem/swap`                       |
| `mem/usage`                      |
| `mem/working_set`                |
| `tcp/CLOSE`                      |
| `tcp/CLOSE_WAIT`                 |
| `tcp/CLOSING`                    |
| `tcp/ESTABLISHED`                |
| `tcp/FIN_WAIT_1`                 |
| `tcp/FIN_WAIT_2`                 |
| `tcp/LAST_ACK`                   |
| `tcp/LISTEN`                     |
| `tcp/SYN_RECV`                   |
| `tcp/SYN_SENT`                   |
| `tcp/TIME_WAIT`                  |
| `tcp6/CLOSE`                     |
| `tcp6/CLOSE_WAIT`                |
| `tcp6/CLOSING`                   |
| `tcp6/ESTABLISHED`               |
| `tcp6/FIN_WAIT_1`                |
| `tcp6/FIN_WAIT_2`                |
| `tcp6/LAST_ACK`                  |
| `tcp6/LISTEN`                    |
| `tcp6/SYN_RECV`                  |
| `tcp6/SYN_SENT`                  |
| `tcp6/TIME_WAIT`                 |

repository: grafana/snap-plugin-collector-cadvisor

repo_name: grafana/snap-plugin-collector-cadvisor


text:
---
title: '4.5.0: 2019-09-23'
date: 2019-09-23T04:00:00.000Z
version: 4.5.0
changelog:
  - API
---
### Added
- Added the Enable Linode Managed ([POST /account/settings/managed-enable](https://www.linode.com/docs/api/account/#linode-managed-enable)) endpoint to Account.
  - This endpoint enables Linode Managed for the entire account and sends a welcome email to the account’s associated email address.
  - [Linode Managed](https://www.linode.com/docs/platform/linode-managed/) is an incident response service that can monitor any software stack or service reachable over TCP or HTTP.

### Changed

- The List Notifications endpoint ([GET /account/notifications](https://www.linode.com/docs/api/account/#notifications-list)) now provides more detailed information when a pending host migration or DC migration ([POST /linode/instances/{linodeId}/migrate](https://www.linode.com/docs/api/linode-instances/#dc-migrationpending-host-migration-initiate)) for a Linode is initiated. This information includes:

  - How many Linodes are in the queue ahead of your Linode. The Linode's position is dynamically generated, so if the notification is retrieved at an interval, it is always up-to-date.

- The convenience endpoint List Object Storage Bucket Contents ([GET /object-storage/buckets/{clusterId}/{bucket}/object-list] (https://www.linode.com/docs/api/object-storage/#object-storage-bucket-contents-list)) now returns two new parameters to help with pagination:
  - `is_truncated`, a boolean which is true if there is another page of objects and
  - `next_marker`, a string value to pass to the `marker` query parameter to get the next page of objects.

### Fixed

- Previously, when restoring a Linode from a backup ([POST /linode/instances/{linodeId}/backups/{backupId}/restore](https://www.linode.com/docs/api/linode-instances/#backup-restore)) with `overwrite:true`, some disks on the Linode were not properly deleted. This bug has been fixed. Additionally, the check to determine if the Linode has enough free disk space during a backup restore has been improved.

- The List Support Tickets endpoint ([GET /support/tickets](https://www.linode.com/docs/api/support/#support-tickets-list)) will now properly honor the `order_by` and `x-filter` query parameters.

repository: linode/developers

branch_name: refs/heads/development

repo_name: linode/developers


text:
---
author: admin
comments: true
date: 2009-03-23 10:38:00+00:00
layout: post
slug: why-im-a-map-maker
title: Why I'm a Map Maker
wordpress_id: 24
categories:
- GIS
- Web Development
tags:
- Google
- LBS
- Maps
- Mashups
---

I remember the first time I used [Google Maps](http://maps.google.com/). I was thrilled with the ability to find places and locate them on a digital map. That was my first exposure to [Geographic Information Systems](http://en.wikipedia.org/wiki/GIS). But I quickly grew out of it after a while and what was majorly because of the lack of localized information.

[caption id="attachment_25" align="alignnone" width="300" caption="Victoria Island roadmap as appeared on Google Maps on 22 March, 2009"][![Roadmap as appeared on Google Maps on 22 March, 2009](/public/uploads/2009/03/staticmap-roadmap-300x300.gif)](/public/uploads/2009/03/staticmap-roadmap.gif)[/caption]

I dabbled into Google Maps mashups and built my first Google Maps application when I was working on my final year project in the University but then I saw little use for it locally.

A few months back, Google announced a community-based mapping project known as [Google Map Maker](http://www.google.com/mapmaker). Google Map Maker enables the people who live in areas that have not been well covered by Google to map their localities using the tools that Google has provided. The implication of this is that you now have the ability to map your village, if you wanted to.

[caption id="attachment_26" align="alignnone" width="300" caption="Google Map Maker tile of Victoria Island as at March 22, 2009"][![Google Map Maker tile of Victoria Island as at March 22, 2009](/public/uploads/2009/03/staticmap-mapmaker-roadpmap-300x300.gif)](/public/uploads/2009/03/staticmap-mapmaker-roadpmap.gif)[/caption]

### What's the motivation?

That's a rather interesting question because I never really gave thought to it when I started creating maps using Google Map Maker but in giving thought to it, I realized that in providing local content on the Internet not only does it makes the Internet richer but it also provides value for the locals. I earlier mentioned how the Mapping service was of little use to me because there wasn't local data but now, with other people mapping different areas within the country, I am able to determine routes before setting out (for instance).

I remember a particular day I was to meet up with someone somewhere in Lagos Mainland. He described the point of meeting as around the intersection of Opebi Link Road. I wasn't sure of the location but then I thought "worst case scenario, I'll ask someone about it." I decided to put Google Map Maker to the test. I did a search for Opebi Link Road and voila, it showed me the location and I was able to know where it was and how to get there.

Imagine then that you are looking for the nearest branch of a particular bank. Apart from having to consult the list of branches from the bank's web site, you can look it up on Google Map Maker. Now eventually, the information will be integrated into Google Maps proper but for now, everything is still available on Google Map Maker.

So what happens if the information you are looking for is not available? Add it! There's no reason why your company's branches or building (or other features like street names, restaurants, churches, mosques, entertainment venues, etc) is not tagged on the map. Information is being added to the map on a daily basis and your contributions are not only helping give your company visibility, but it's also adding value to others who might find that information useful when the need arises.

extension: markdown

gha_language: HTML


text:
# Variables

Variables allow you to inject pieces of information dynamically into your shortcuts when executing them. A variable consists of a name and a value which is resolved at execution time, based on its type. For some variable types this means that a prompt dialog is shown that asks for a value, others can be resolved without user input. They are global, meaning that they do not belong to a specific shortcut but can be used by all of them.

For more details on when variables are resolved see the [Execution Flow](execution-flow.md) documentation.

## Using Variables

You can insert a placeholder for a variable into your shortcuts' url, requests parameters, request body, authentication and header fields by clicking the *"{ }"* button next to the input field and selecting a variable.

When executing a shortcut that contains variable placeholders all of them are resolved according to their type.

You can also insert these placeholders into some of your variables, i.e., you can have variables reference other variables, and you can use them when writing [scripts](scripting.md#variables).

## Variable Types

When creating a variable, you have to select its type. The type dictates how the variable will receive its value, and what types of values it supports.

### Static Variable

A *static variable* (formerly called *constant*) stores a static value, until explicitly changed. It can be used to store a piece of information that is shared across multiple shortcut, such as an authentication token or a domain name. This way it can easily be changed.

It is also possible to change the value of a static variable programmatically before or after a shortcut runs, e.g. to store parts of a HTTP response into it. See the [Scripting](scripting.md#variables) documentation for more details.

### Toggle

The *toggle* type consists of a list of values. Every time it is used it resolves to the next value in the list. When the last value is reached it starts again from the first.

### Multiple-Choice

The *multiple choice* type consists of a list of options, each of which has a value and a label. It triggers a dialog from which one of the options can be selected.

It can also be configured to allow selecting multiple values.

### Text, Number and Password

The *text*, *number* and *password* types trigger a prompt dialog where a value can be entered into a text field.

### Number Slider

The *number slider* type is similar to the *number* type. It allows you to pick a number. However, the number is entered using a horizontal slider, for which you can define the minimum and maximum value, as well as the step size.

### Date and Time

The *date* and *time* types trigger a prompt dialog where a date or time can be selected. The output format can be specified according to Android's [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat.html).

### Color

The *color* type triggers a prompt dialog where a color can be selected. Its value is returned in RGB hex format (e.g. ff0000 for red).

## Sharing Values into Variables
In the advanced settings section of a variable you can mark it as *Allow 'Share …'*. This makes it possible to provide the value of this variable through Android's *Share*-dialog, e.g., by sharing a URL or text snippet from another app. The variable will then assume the shared value during execution.

repository: jdimpson/HTTP-Shortcuts

repo_name: jdimpson/HTTP-Shortcuts


text:
# Tweets Analysis ui

Tweet analysis is an interactive web-based app that enable users to see the analysis of hashtag, user mention or keyword fot twitter data for specific period of time.

# Getting started

Installing and running Tweet Crawler on your machine should be a pretty straightforward process. In order to do so, you first need to install suitable versions of Docker and Docker Compose.

Making use of Docker (and Docker Compose) greatly simplifies the Tweet Crawler setup process and will make it easier for you to run this program on the platform of your choice.

If you already have up-to-date versions of these programs, feel free to skip straight to the Install and Run section.

## Prerequisites
We've included links below to installation instructions for Docker Community Edition on three popular platforms: Windows, Mac, and Ubuntu (Linux).

After following these instructions, you will be able to directly run the commands in the Install and Run section.

### Windows
* Visit the [ Install Docker for Windows](https://docs.docker.com/docker-for-windows/install/) page
* Follow the instructions listed in the section called [Install Docker for Windows Desktop App](https://docs.docker.com/docker-for-windows/install/#install-docker-for-windows-desktop-app)
### Mac
* Visit the [Install Docker for Mac ](https://docs.docker.com/docker-for-mac/install/) page
* After downloading the .dmg file, follow the instructions listed in the section called [Install and Run Docker for Mac! ](https://docs.docker.com/docker-for-mac/install/#install-and-run-docker-for-mac)
### Ubuntu
* Visit the Get [I Docker CE for Ubuntu ](https://docs.docker.com/install/linux/docker-ce/ubuntu/)page
* Follow the instructions listed under the [Install Docker CE ](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce) section
* To install Docker Compose, visit the Install [Install Docker CE ](https://docs.docker.com/compose/install/) page
* Follow the instructions under the [Install Docker Compose ](https://docs.docker.com/compose/install/#install-compose)section
* Follow the [Linux post-install ](https://docs.docker.com/install/linux/linux-postinstall/) instructions

### Install and Run
If you've fulfilled the above prerequisites, it's very simple to download and run the server to be able call the apis from the user interface.

Clone the project repository from Github

`cd ~`
`git clone https://github.com/qcrisw/tweets_analysis.git`
`cd tweet-analysis`

### Running Tweets analysis server

`docker-compose up`

Now the server is working locally on ur machine on port 3000

### Testing the UI

Go to client folder, open index.html in the browser. No you can start search for specific search topic and see the results..

# Built With
* Node js,[ Express framework ](https://expressjs.com/)
* [Promise js](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
* [Mongo db](https://www.mongodb.com/)
* HTML5, CSS3, bootstrap, jQuery

# License
This project is licensed under the MIT License inside QCRI


text:
---
title: Simian and CruiseControl.NET
disqus_identifier: 2006-03-simian-and-cruisecontrolnet
comments: true
---

I've been using [Simian][1] for quite a while to analyze code and help me find areas that could use refactoring. However, only recently  have I introduced Simian into my continuous integration process here at home. I had quite a time getting builds to work after doing this.

The easiest way to get Simian into CC.NET is to set up an exec task in your ccnet.config file's task section, as follows:

``` xml
<project>
    <tasks>
        <exec>
            <executable>c:\tools\simian\bin\simian-2.2.8.exe</executable>
            <buildArgs>-recurse=*.cs -formatter=xml:build\log\simian.xml</buildArgs>
        </exec>
    </tasks>
</project>
```

Id noticed that quite often builds would fail for no apparent reason. The CC.NET log looked clean. Finally, after reviewing one of my successful builds I noticed the simian section had an area that said 'failOnDuplication=true'.

Assuming that this was my problem, I looked into it a little further. Seems that simian is by default set up to return 1 on duplications, which triggers a failure in both nant and cc.net.

The easiest way to get around this is to pass another argument in your build args section:

`-recurse=*.cs -formatter=xml:build\log\simian.xml -failOnDuplication`

Problem solved! :)

I understand the reasons for having simian fail on duplication, however, I disagree with this being the default. I hope that this will change in a future build.

[1]:http://www.redhillconsulting.com.au/products/simian/


text:
# Streaming Telemetry 101

In this tutorial you will learn how to configure streaming telemetry for IOS XE, as well as setup collectors, transform/load the data into a time series database, and visualize it using Grafana.

## The Environment
This environment consists of several virtualized devices and software components.

* [CSR 1000v](https://developer.cisco.com/docs/ios-xe/#!developer-tooling-quick-start-guide/virtual-ios-xe-device-options) (IOS XE)
* [IOS XRv](https://xrdocs.github.io/application-hosting/tutorials/iosxr-vagrant-quickstart) (IOS XR)
* [Cisco Nexus 9000v](https://developer.cisco.com/docs/nx-os/#!developer-tooling/developer-tooling) (NX-OS)
* Ubuntu Server

***Note:** Streaming Telemetry on IOS XRv and Cisco Nexus 9000v are outside the scope of Streaming Telemetry 101, but there for you to to develop around in the Sandbox.

Running on the Ubuntu server are:

1. [NETCONF Client](https://github.com/CiscoDevNet/ncc) and [Pipeline](https://github.com/cisco/bigmuddy-network-telemetry-pipeline) (Consumers)
2. [Kafka](https://kafka.apache.org/) (Message Bus)
3. [Apache Spark](https://spark.apache.org/streaming/) with [Jupyter](http://jupyter.org/) (Transform the data into the time-series database format)
4. [OpenTSDB](http://opentsdb.net/) (Time series database)
5. [Grafana](https://grafana.com/) (Visualization)

![environment](environment.png)

## Start the Databases
**This step must happen first!** For this setup, we are using Apache Spark as the transformer/loader and OpenTSDB as the time series database.

1. SSH into Ubuntu Server
   ```bash
   # Password: Cisco1234!
   ssh<EMAIL_ADDRESS>   ```

2. Download the latest code for the project

   ```bash
   cd telemetry_stacks
   git pull
   ```

1. Start the Docker Stacks from the directory `telemetry_stacks`

   ```bash
   docker-compose -f docker-compose.yml -f docker-compose-opentsdb.yml up -d
   ```

## Setting up Streaming Telemetry on IOS XE
IOS XE exposes streaming telemetry via NETCONF using [IETF YANG Push / YANG Datastore Subscription](https://datatracker.ietf.org/doc/draft-ietf-netconf-yang-push/). This is a draft RFC which Cisco has added support for in a fork of [ncclient](https://github.com/CiscoDevNet/ncclient) and developed useful wrappers for via [ncc](https://github.com/CiscoDevNet/ncc). It can be used like a script or programatically with Python. Due to being NETCONF based, only XML is supported in the encoding.

### Configure Streaming Telemetry

1. SSH into the CSR 1000v (IOS XE)
   ```bash
   # Password: Cisco1234!
   ssh<EMAIL_ADDRESS>   ```
2. Configure NETCONF-YANG and NETCONF
   ```
   CSR1000V#conf t
   Enter configuration commands, one per line.  End with CNTL/Z.
   CSR1000V(config)#netconf-yang
   CSR1000V(config)#exit
   CSR1000V#
   ```

### Turn On Consumer
First we will ensure that we are able to stream data, then direct the data to our Kafka broker to be buffered until we are able to consume it into the database.

1. SSH into Server
   ```bash
   # Password: Cisco1234!
   ssh<EMAIL_ADDRESS>   ```
2. Verify we are able to stream data by printing it to stdout. If it does not immediately work, wait a couple more seconds.
   ```bash
   cd telemetry_stacks/consumers/xe/
   pipenv shell
   # Ctrl+C to halt
   python print_telemetry.py
   ```

   If everything is working, you should see an output of telemetry data in XML similar to:

   ```xml
   .
   .
   <datastore-contents-xml xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-push">
     <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
       <interface>
         <name>Control Plane</name>
         <statistics>
           <discontinuity-time>2018-05-31T14:49:17.000193+00:00</discontinuity-time>
           <in-octets>0</in-octets>
           <in-unicast-pkts>0</in-unicast-pkts>
           <in-broadcast-pkts>0</in-broadcast-pkts>
           <in-multicast-pkts>0</in-multicast-pkts>
           <in-discards>0</in-discards>
           <in-errors>0</in-errors>
           <in-unknown-protos>0</in-unknown-protos>
           <out-octets>0</out-octets>
           <out-unicast-pkts>0</out-unicast-pkts>
           <out-broadcast-pkts>0</out-broadcast-pkts>
           <out-multicast-pkts>0</out-multicast-pkts>
           <out-discards>0</out-discards>
           <out-errors>0</out-errors>
         </statistics>
       </interface>
   .
   .
   .
   ```

3. If everything is working, let's now send the data to Kafka. Instead of running `print_telemetry.py`, let's run `kafka_telemetry.py` in the background.
  ```shell
  # All log statements will be in telemetry.log
  python kafka_telemetry.py &> telemetry.log &
  ```

#### Start the Transformer

1. Navigate to http://<IP_ADDRESS>:8888 in a browser, the password is `cisco1234`

2. Click on the folder [telemetry](http://<IP_ADDRESS>:8888/notebooks/telemetry/)

3. Click on the file [Kafka_OTSDB_XE.ipynb](http://<IP_ADDRESS>:8888/notebooks/telemetry/Kafka_OTSDB_XE.ipynb)

4. Click on the first tile, and click `Run` on the Jupyter command bar. Click on all the following tiles except for the last which which contains `ssc.stop()`.

   ** Make sure you do not click `run` on `ssc.stop`**

#### Create a Graph

1. Navigate to http://<IP_ADDRESS>:3000 in a browser, the login credentials are `admin`/`admin`.

2. Click on `Add Data Source` in the center of the screen.

3. Change the details to the following:

   	Name: `OTSDB`

   	Type: `OpenTSDB`

   	URL:  `http://opentsdb:4242`

4. Click on `Save & Test` at the bottom of the page. If everything is working you should see a green box stating "Data source is working."

5. Click on the `+` icon on the left toolbar and create a new dashboard

6. Add a graph

7. Click on the panel and select "Edit" or press `e` on your keyboard

8. Change the `Metric` to `in-octets` and `Aggregator` to `last` and check the `Rate` checkbox

9. Click the refresh icon on the top right of the box, you should now see a graph of your data!

## Conclusion

Now that you have Streaming Telemetry working on IOS XE, try making it work with NX-OS and IOS XR using the learning labs and other guides as reference. This environment is meant for you to be able to play around with the different Cisco operating systems and create your own collectors for databases you use in your environment.

gha_language: Jupyter Notebook


text:
# gRPC Basics: Tonic

This tutorial, adapted from [grpc-go], provides a basic introduction to working with gRPC
and Tonic. By walking through this example you'll learn how to:

- Define a service in a `.proto` file.
- Generate server and client code.
- Write a simple client and server for your service.

It assumes you are familiar with [protocol buffers] and basic Rust. Note that the example in
this tutorial uses the proto3 version of the protocol buffers language, you can find out more in the
[proto3 language guide][proto3].

[grpc-go]: https://github.com/grpc/grpc-go/blob/master/examples/gotutorial.md
[protocol buffers]: https://developers.google.com/protocol-buffers/docs/overview
[proto3]: https://developers.google.com/protocol-buffers/docs/proto3

## Why use gRPC?

Our example is a simple route mapping application that lets clients get information about features
on their route, create a summary of their route, and exchange route information such as traffic
updates with the server and other clients.

With gRPC we can define our service once in a `.proto` file and implement clients and servers in
any of gRPC's supported languages, which in turn can be run in environments ranging from servers
inside Google to your own tablet - all the complexity of communication between different languages
and environments is handled for you by gRPC. We also get all the advantages of working with
protocol buffers, including efficient serialization, a simple IDL, and easy interface updating.

## Prerequisites

To run the sample code and walk through the tutorial, the only prerequisite is Rust itself.
[rustup] is a convenient tool to install it, if you haven't already.

[rustup]: https://rustup.rs

## Running the example

Clone or download Tonic's repository:

```shell
$ git clone https://github.com/hyperium/tonic.git
```

Change your current directory to Tonic's repository root:
```shell
$ cd tonic
```

Run the server
```shell
$ cargo run --bin routeguide-server
```

In a separate shell, run the client
```shell
$ cargo run --bin routeguide-client
```

You should see some logging output flying past really quickly on both terminal windows. On the
shell where you ran the client binary, you should see the output of the bidirectional streaming rpc,
printing 1 line per second:

```
NOTE = RouteNote { location: Some(Point { latitude: 409146139, longitude: -746188906 }), message: "at 1.000319208s" }
```

If you scroll up you should see the output of the other 3 request types: simple rpc, server-side
streaming and client-side streaming.

## Project setup

We will develop our example from scratch in a new crate:

```shell
$ cargo new routeguide
$ cd routeguide
```

## Defining the service

Our first step is to define the gRPC *service* and the method *request* and *response* types using
[protocol buffers]. We will keep our `.proto` files in a directory in our crate's root.
Note that Tonic does not really care where our `.proto` definitions live. We will see how to use
different [code generation configuration](#tonic-build) later in the tutorial.

```shell
$ mkdir proto && touch proto/route_guide.proto
```

You can see the complete `.proto` file in
[examples/proto/routeguide/route_guide.proto][routeguide-proto].

To define a service, you specify a named `service` in your `.proto` file:

```proto
service RouteGuide {
   ...
}
```

Then you define `rpc` methods inside your service definition, specifying their request and response
types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide`
service:

- A *simple RPC* where the client sends a request to the server and waits for a response to come
back, just like a normal function call.
```proto
   // Obtains the feature at a given position.
   rpc GetFeature(Point) returns (Feature) {}
```

- A *server-side streaming RPC* where the client sends a request to the server and gets a stream
to read a sequence of messages back. The client reads from the returned stream until there are
no more messages. As you can see in our example, you specify a server-side streaming method by
placing the `stream` keyword before the *response* type.
```proto
  // Obtains the Features available within the given Rectangle.  Results are
  // streamed rather than returned at once (e.g. in a response message with a
  // repeated field), as the rectangle may cover a large area and contain a
  // huge number of features.
  rpc ListFeatures(Rectangle) returns (stream Feature) {}
```

- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to
the server. Once the client has finished writing the messages, it waits for the server to read them
all and return its response. You specify a client-side streaming method by placing the `stream`
keyword before the *request* type.
```proto
  // Accepts a stream of Points on a route being traversed, returning a
  // RouteSummary when traversal is completed.
  rpc RecordRoute(stream Point) returns (RouteSummary) {}
```

- A *bidirectional streaming RPC* where both sides send a sequence of messages. The two streams
operate independently, so clients and servers can read and write in whatever
order they like: for example, the server could wait to receive all the client messages before
writing its responses, or it could alternately read a message then write a message, or some other
combination of reads and writes. The order of messages in each stream is preserved. You specify
this type of method by placing the `stream` keyword before both the request and the response.
```proto
  // Accepts a stream of RouteNotes sent while a route is being traversed,
  // while receiving other RouteNotes (e.g. from other users).
  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
```

Our `.proto` file also contains protocol buffer message type definitions for all the request and
response types used in our service methods - for example, here's the `Point` message type:
```proto
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}
```

[routeguide-proto]: https://github.com/hyperium/tonic/blob/master/examples/proto/routeguide/route_guide.proto

## Generating client and server code

Tonic can be configured to generate code as part cargo's normal build process. This is very
convenient because once we've set everything up, there is no extra step to keep the generated code
and our `.proto` definitions in sync.

Behind the scenes, Tonic uses [PROST!] to handle protocol buffer serialization and code
generation.

Edit `Cargo.toml` and add all the dependencies we'll need for this example:

```toml
[dependencies]
tonic = "0.7"
prost = "0.10"
futures-core = "0.3"
futures-util = "0.3"
tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "sync", "time"] }
tokio-stream = "0.1"

async-stream = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.7"

[build-dependencies]
tonic-build = "0.7"
```

Create a `build.rs` file at the root of your crate:

```rust
fn main() {
    tonic_build::compile_protos("proto/route_guide.proto")
        .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
}
```

```shell
$ cargo build
```

That's it. The generated code contains:

- Struct definitions for message types `Point`, `Rectangle`, `Feature`, `RouteNote`, `RouteSummary`.
- A service trait we'll need to implement: `route_guide_server::RouteGuide`.
- A client type we'll use to call the server: `route_guide_client::RouteGuideClient<T>`.

If your are curious as to where the generated files are, keep reading. The mystery will be revealed
soon! We can now move on to the fun part.

[PROST!]: https://github.com/danburkert/prost

## Creating the server

First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC
clients, you can skip this section and go straight to [Creating the client](#client)
(though you might find it interesting anyway!).

There are two parts to making our `RouteGuide` service do its job:

- Implementing the service trait generated from our service definition.
- Running a gRPC server to listen for requests from clients.

You can find our example `RouteGuide` server in
[examples/src/routeguide/server.rs][routeguide-server].

[routeguide-server]: https://github.com/hyperium/tonic/blob/master/examples/src/routeguide/server.rs

### Implementing the RouteGuide server trait

We can start by defining a struct to represent our service, we can do this on `main.rs` for now:

```rust
#[derive(Debug)]
struct RouteGuideService;
```

Next, we need to implement the `route_guide_server::RouteGuide` trait that is generated in our build step.
The generated code is placed inside our target directory, in a location defined by the `OUT_DIR`
environment variable that is set by cargo. For our example, this means you can find the generated
code in a path similar to `target/debug/build/routeguide/out/routeguide.rs`.

You can learn more about `build.rs` and the `OUT_DIR` environment variable in the [cargo book].

We can use Tonic's `include_proto` macro to bring the generated code into scope:

```rust
pub mod routeguide {
    tonic::include_proto!("routeguide");
}

use routeguide::route_guide_server::{RouteGuide, RouteGuideServer};
use routeguide::{Feature, Point, Rectangle, RouteNote, RouteSummary};
```

**Note**: The token passed to the `include_proto` macro (in our case "routeguide") is the name of
the package declared in our `.proto` file, not a filename, e.g "routeguide.rs".

With this in place, we can stub out our service implementation:

```rust
use futures_core::Stream;
use std::pin::Pin;
use std::sync::Arc;
use tokio::sync::mpsc;
use tonic::{Request, Response, Status};
use tokio_stream::wrappers::ReceiverStream;
```

```rust
#[tonic::async_trait]
impl RouteGuide for RouteGuideService {
    async fn get_feature(&self, _request: Request<Point>) -> Result<Response<Feature>, Status> {
        unimplemented!()
    }

    type ListFeaturesStream = ReceiverStream<Result<Feature, Status>>;

    async fn list_features(
        &self,
        _request: Request<Rectangle>,
    ) -> Result<Response<Self::ListFeaturesStream>, Status> {
        unimplemented!()
    }

    async fn record_route(
        &self,
        _request: Request<tonic::Streaming<Point>>,
    ) -> Result<Response<RouteSummary>, Status> {
        unimplemented!()
    }

    type RouteChatStream = Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send  + 'static>>;

    async fn route_chat(
        &self,
        _request: Request<tonic::Streaming<RouteNote>>,
    ) -> Result<Response<Self::RouteChatStream>, Status> {
        unimplemented!()
    }
}
```

**Note**: The `tonic::async_trait` attribute macro adds support for async functions in traits. It
uses [async-trait] internally. You can learn more about `async fn` in traits in the [async book].

[cargo book]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
[async-trait]: https://github.com/dtolnay/async-trait
[async book]: https://rust-lang.github.io/async-book/07_workarounds/05_async_in_traits.html

### Server state
Our service needs access to an immutable list of features. When the server starts, we are going to
deserialize them from a json file and keep them around as our only piece of shared state:

```rust
#[derive(Debug)]
pub struct RouteGuideService {
    features: Arc<Vec<Feature>>,
}
```

Create the json data file and a helper module to read and deserialize our features.

```shell
$ mkdir data && touch data/route_guide_db.json
$ touch src/data.rs
```

You can find our example json data in [examples/data/route_guide_db.json][route-guide-db] and
the corresponding `data` module to load and deserialize it in
[examples/routeguide/data.rs][data-module].

**Note:** If you are following along, you'll need to change the data file's path  from
`examples/data/route_guide_db.json` to `data/route_guide_db.json`.

Next, we need to implement `Hash` and `Eq` for `Point`, so we can use point values as map keys:

```rust
use std::hash::{Hasher, Hash};
```

```rust
impl Hash for Point {
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        self.latitude.hash(state);
        self.longitude.hash(state);
    }
}

impl Eq for Point {}

```

Lastly, we need implement two helper functions: `in_range` and `calc_distance`. We'll use them
when performing feature lookups. You can find them in
[examples/src/routeguide/server.rs][in-range-fn].

[route-guide-db]: https://github.com/hyperium/tonic/blob/master/examples/data/route_guide_db.json
[data-module]: https://github.com/hyperium/tonic/blob/master/examples/src/routeguide/data.rs
[in-range-fn]: https://github.com/hyperium/tonic/blob/master/examples/src/routeguide/server.rs#L174

#### Request and Response types
All our service methods receive a `tonic::Request<T>` and return a
`Result<tonic::Response<T>, tonic::Status>`. The concrete type of `T` depends on how our methods
are declared in our *service* `.proto` definition. It can be either:

- A single value, e.g `Point`, `Rectangle`, or even a message type that includes a repeated field.
- A stream of values, e.g. `impl Stream<Item = Result<Feature, tonic::Status>>`.

#### Simple RPC
Let's look at the simplest method first, `get_feature`, which just gets a `tonic::Request<Point>`
from the client and tries to find a feature at the given `Point`. If no feature is found, it returns
an empty one.

```rust
async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
    for feature in &self.features[..] {
        if feature.location.as_ref() == Some(request.get_ref()) {
            return Ok(Response::new(feature.clone()));
        }
    }

    Ok(Response::new(Feature::default()))
}
```

#### Server-side streaming RPC
Now let's look at one of our streaming RPCs. `list_features` is a server-side streaming RPC, so we
need to send back multiple `Feature`s to our client.

```rust
type ListFeaturesStream = ReceiverStream<Result<Feature, Status>>;

async fn list_features(
    &self,
    request: Request<Rectangle>,
) -> Result<Response<Self::ListFeaturesStream>, Status> {
    let (mut tx, rx) = mpsc::channel(4);
    let features = self.features.clone();

    tokio::spawn(async move {
        for feature in &features[..] {
            if in_range(feature.location.as_ref().unwrap(), request.get_ref()) {
                tx.send(Ok(feature.clone())).await.unwrap();
            }
        }
    });

    Ok(Response::new(ReceiverStream::new(rx)))
}
```

Like `get_feature`, `list_features`'s input is a single message, a `Rectangle` in this
case. This time, however, we need to return a stream of values, rather than a single one.
We create a channel and spawn a new asynchronous task where we perform a lookup, sending
the features that satisfy our constraints into the channel.

The `Stream` half of the channel is returned to the caller, wrapped in a `tonic::Response`.

#### Client-side streaming RPC
Now let's look at something a little more complicated: the client-side streaming method
`record_route`, where we get a stream of `Point`s from the client and return a single `RouteSummary`
with information about their trip. As you can see, this time the method receives a
`tonic::Request<tonic::Streaming<Point>>`.

```rust
use std::time::Instant;
use futures_util::StreamExt;
```

```rust
async fn record_route(
    &self,
    request: Request<tonic::Streaming<Point>>,
) -> Result<Response<RouteSummary>, Status> {
    let mut stream = request.into_inner();

    let mut summary = RouteSummary::default();
    let mut last_point = None;
    let now = Instant::now();

    while let Some(point) = stream.next().await {
        let point = point?;
        summary.point_count += 1;

        for feature in &self.features[..] {
            if feature.location.as_ref() == Some(&point) {
                summary.feature_count += 1;
            }
        }

        if let Some(ref last_point) = last_point {
            summary.distance += calc_distance(last_point, &point);
        }

        last_point = Some(point);
    }

    summary.elapsed_time = now.elapsed().as_secs() as i32;

    Ok(Response::new(summary))
}
```

`record_route` is conceptually simple: we get a stream of `Points` and fold it into a `RouteSummary`.
In other words, we build a summary value as we process each `Point` in our stream, one by one.
When there are no more `Points` in our stream, we return the `RouteSummary` wrapped in a
`tonic::Response`.

#### Bidirectional streaming RPC
Finally, let's look at our bidirectional streaming RPC `route_chat`, which receives a stream
of `RouteNote`s and returns  a stream of `RouteNote`s.

```rust
use std::collections::HashMap;
```

```rust
type RouteChatStream =
    Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send  + 'static>>;

async fn route_chat(
    &self,
    request: Request<tonic::Streaming<RouteNote>>,
) -> Result<Response<Self::RouteChatStream>, Status> {
    let mut notes = HashMap::new();
    let mut stream = request.into_inner();

    let output = async_stream::try_stream! {
        while let Some(note) = stream.next().await {
            let note = note?;

            let location = note.location.clone().unwrap();

            let location_notes = notes.entry(location).or_insert(vec![]);
            location_notes.push(note);

            for note in location_notes {
                yield note.clone();
            }
        }
    };

    Ok(Response::new(Box::pin(output)
        as Self::RouteChatStream))

}
```

`route_chat` uses the [async-stream] crate to perform an asynchronous transformation
from one (input) stream to another (output) stream. As the input is processed, each value is
inserted into the notes map, yielding a clone of the original `RouteNote`. The resulting stream
is then returned to the caller. Neat.

**Note**: The funky `as` cast is needed due to a limitation in the rust compiler. This is expected
to be fixed soon.

[async-stream]: https://github.com/tokio-rs/async-stream

### Starting the server

Once we've implemented all our methods, we also need to start up a gRPC server so that clients can
actually use our service. This is how our `main` function looks like:

```rust
mod data;
use tonic::transport::Server;
```

```rust
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:10000".parse().unwrap();

    let route_guide = RouteGuideService {
        features: Arc::new(data::load()),
    };

    let svc = RouteGuideServer::new(route_guide);

    Server::builder().add_service(svc).serve(addr).await?;

    Ok(())
}
```

To handle requests, `Tonic` uses [Tower] and [hyper] internally. What this means,
among other things, is that we have a flexible and composable stack we can build on top of. We can,
for example, add an [interceptor][authentication-example] to process requests before they reach our service
methods.

[Tower]: https://github.com/tower-rs
[hyper]: https://github.com/hyperium/hyper
[authentication-example]: https://github.com/hyperium/tonic/blob/master/examples/src/authentication/server.rs#L56

## Creating the client

In this section, we'll look at creating a Tonic client for our `RouteGuide` service. You can see our
complete example client code in [examples/src/routeguide/client.rs][routeguide-client].

Our crate will have two binary targets: `routeguide-client` and `routeguide-server`. We need to
edit our `Cargo.toml` accordingly:

```toml
[[bin]]
name = "routeguide-server"
path = "src/server.rs"

[[bin]]
name = "routeguide-client"
path = "src/client.rs"
```

Rename `main.rs` to `server.rs` and create a new file `client.rs`.

```shell
$ mv src/main.rs src/server.rs
$ touch src/client.rs
```

To call service methods, we first need to create a gRPC *client* to communicate with the server. Like in the server
case, we'll start by bringing the generated code into scope:

```rust
pub mod routeguide {
    tonic::include_proto!("routeguide");
}

use routeguide::route_guide_client::RouteGuideClient;
use routeguide::{Point, Rectangle, RouteNote};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = RouteGuideClient::connect("http://[::1]:10000").await?;

     Ok(())
}
```

Same as in the server implementation, we start by bringing our generated code into scope. We then
create a client in our main function, passing the server's full URL to `RouteGuideClient::connect`.
Our client is now ready to make service calls. Note that `client` is mutable, this is because it
needs to manage internal state.

[routeguide-client]: https://github.com/hyperium/tonic/blob/master/examples/src/routeguide/client.rs

### Calling service methods
Now let's look at how we call our service methods. Note that in Tonic, RPCs are asynchronous,
which means that RPC calls need to be `.await`ed.

#### Simple RPC
Calling the simple RPC `get_feature` is as straightforward as calling a local method:

```rust
use tonic::Request;
```

```rust
let response = client
    .get_feature(Request::new(Point {
        latitude: 409146138,
        longitude: -746188906,
    }))
    .await?;

println!("RESPONSE = {:?}", response);
```
We call the `get_feature` client method, passing a single `Point` value wrapped in a
`tonic::Request`. We get a `Result<tonic::Response<Feature>, tonic::Status>` back.

#### Server-side streaming RPC
Here's where we call the server-side streaming method `list_features`, which returns a stream of
geographical `Feature`s.

```rust
use tonic::transport::Channel;
use std::error::Error;
```

```rust
async fn print_features(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
    let rectangle = Rectangle {
        lo: Some(Point {
            latitude: 400000000,
            longitude: -750000000,
        }),
        hi: Some(Point {
            latitude: 420000000,
            longitude: -730000000,
        }),
    };

    let mut stream = client
        .list_features(Request::new(rectangle))
        .await?
        .into_inner();

    while let Some(feature) = stream.message().await? {
        println!("NOTE = {:?}", feature);
    }

    Ok(())
}
```

As in the simple RPC, we pass a single value request. However, instead of getting a
single value back, we get a stream of `Features`.

We use the the `message()` method from the `tonic::Streaming` struct to repeatedly read in the
server's responses to a response protocol buffer object (in this case a `Feature`) until there are
no more messages left in the stream.

#### Client-side streaming RPC
The client-side streaming method `record_route` takes a stream of `Point`s and returns a single
`RouteSummary` value.

```rust
use rand::rngs::ThreadRng;
use rand::Rng;
use futures_util::stream;
```

```rust
async fn run_record_route(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
    let mut rng = rand::thread_rng();
    let point_count: i32 = rng.gen_range(2..100);

    let mut points = vec![];
    for _ in 0..=point_count {
        points.push(random_point(&mut rng))
    }

    println!("Traversing {} points", points.len());
    let request = Request::new(stream::iter(points));

    match client.record_route(request).await {
        Ok(response) => println!("SUMMARY: {:?}", response.into_inner()),
        Err(e) => println!("something went wrong: {:?}", e),
    }

    Ok(())
}
```

```rust
fn random_point(rng: &mut ThreadRng) -> Point {
    let latitude = (rng.gen_range(0..180) - 90) * 10_000_000;
    let longitude = (rng.gen_range(0..360) - 180) * 10_000_000;
    Point {
        latitude,
        longitude,
    }
}
```

We build a vector of a random number of `Point` values (between 2 and 100) and then convert
it into a `Stream` using the `futures::stream::iter` function. This is a cheap an easy way to get
a stream suitable for passing into our service method. The resulting stream is then wrapped in a
`tonic::Request`.

#### Bidirectional streaming RPC

Finally, let's look at our bidirectional streaming RPC. The `route_chat` method takes a stream
of `RouteNotes` and returns either another stream of `RouteNotes` or an error.

```rust
use std::time::Duration;
use tokio::time;
```

```rust
async fn run_route_chat(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
    let start = time::Instant::now();

    let outbound = async_stream::stream! {
        let mut interval = time::interval(Duration::from_secs(1));

        while let time = interval.tick().await {
            let elapsed = time.duration_since(start);
            let note = RouteNote {
                location: Some(Point {
                    latitude: 409146138 + elapsed.as_secs() as i32,
                    longitude: -746188906,
                }),
                message: format!("at {:?}", elapsed),
            };

            yield note;
        }
    };

    let response = client.route_chat(Request::new(outbound)).await?;
    let mut inbound = response.into_inner();

    while let Some(note) = inbound.message().await? {
        println!("NOTE = {:?}", note);
    }

    Ok(())
}
```
In this case, we use the [async-stream] crate to generate our outbound stream, yielding
`RouteNote` values in one second intervals. We then iterate over the stream returned by
the server, printing each value in the stream.

## Try it out!

### Run the server
```shell
$ cargo run --bin routeguide-server
```

### Run the client
```shell
$ cargo run --bin routeguide-client
```

## Appendix

### tonic_build configuration

Tonic's default code generation configuration is convenient for self contained examples and small
projects. However, there are some cases when we need a slightly different workflow. For example:

- When building rust clients and servers in different crates.
- When building a rust client or server (or both) as part of a larger, multi-language project.
- When we want editor support for the generate code and our editor does not index the generated
files in the default location.

More generally, whenever we want to keep our `.proto` definitions in a central place and generate
code for different crates or different languages, the default configuration is not enough.

Luckily, `tonic_build` can be configured to fit whatever workflow we need. Here are just two
possibilities:

1)  We can keep our `.proto` definitions in a separate crate and generate our code on demand, as
opposed to at build time, placing the resulting modules wherever we need them.

`main.rs`

```rust
fn main() {
    tonic_build::configure()
        .build_client(false)
        .out_dir("another_crate/src/pb")
        .compile(&["path/my_proto.proto"], &["path"])
        .expect("failed to compile protos");
}
```

On `cargo run`, this will generate code for the client only, and place the resulting file in
`another_crate/src/pb`.

2) Similarly, we could also keep the `.proto` definitions in a separate crate and then use that
crate as a direct dependency wherever we need it.

repository: bmwill/tonic

repo_name: bmwill/tonic


text:
## 967. Numbers With Same Consecutive Differences

Return all **non-negative** integers of length ```n``` such that the absolute difference between every two consecutive digits is ```k```.

Note that **every** number in the answer **must not** have leading zeros. For example, ```01``` has one leading zero and is invalid.

You may return the answer in **any order**.

### Example 1:
```
Input: n = 3, k = 7
Output: [181,292,707,818,929]
Explanation: Note that 070 is not a valid number, because it has leading zeroes.
```
### Example 2:
```
Input: n = 2, k = 1
Output: [10,12,21,23,32,34,43,45,54,56,65,67,76,78,87,89,98]
```

### Constraints:

* ```2 <= n <= 9```
* ```0 <= k <= 9```

repository: stdstring/leetcode

repo_name: stdstring/leetcode


text:
# petit-game-lib

Game development library for petit games.

## Demo

[SINE CIRCUS](https://abagames.github.io/petit-game-lib/sinecircus/)

[![SINE CIRCUS screenshot](docs/screenshots/sinecircus.gif)](https://abagames.github.io/petit-game-lib/sinecircus/)

[MAZTIC](https://abagames.github.io/petit-game-lib/maztic/index.html)

[![MAZTIC screenshot](docs/screenshots/maztic.gif)](https://abagames.github.io/petit-game-lib/maztic/index.html)

[SKI ZONE](https://abagames.github.io/petit-game-lib/skizone/)

[![SKI ZONE screenshot](docs/screenshots/skizone.gif)](https://abagames.github.io/petit-game-lib/skizone/)

repository: abagames/petit-game-lib

repo_name: abagames/petit-game-lib


text:
---
title: 'ELF Symbol Upload'
---

`sentry-cli` can upload ELF symbols generated on various Linux distributions to Sentry to allow symbolication of Linux and Android app crashes. ELF stands for _Executable and Linkable Format_, the file format used for binaries on Linux.

Unlike other platforms, there is no standardized container for debug symbols. They are part of the binary (executable or library) and stripped when generating release builds due to their size. However, there is a way to retain them in a separate file (either in a different location or with `.debug` extension):

```bash
# There is an executable called "binary" in the CWD
objcopy --only-keep-debug binary binary.debug
strip -g binary
objcopy --add-gnu-debug-link=binary.debug binary
```

Shared libraries installed via package managers usually provide their debugging information in separate `*-dev` packages and put it in locations like `/usr/local/debug/...`. To receive symbolicated stack traces from those libraries, make sure to also upload their symbols in addition to your app’s symbols.

## Basic Upload

Use `upload-dif` to upload ELF symbols and specify the `elf` type. The command will recurively scan the provided folders or ZIP archives. If you stripped debug information into separate files, pass the `--no-bin` option to skip stripped executables or libraries.

{% capture __alert_content -%}
Because debug files belong to projects, you will need to specify the organization and project you are working with. For more information about this refer to [Working with Projects]({%- link _documentation/learn/cli/configuration.md -%}#sentry-cli-working-with-projects).
{%- endcapture -%}
{%- include components/alert.html
  title="Note"
  content=__alert_content
%}

All recent compilers and linkers generate a unique build ID and even retain it while stripping binaries. `sentry-cli` uses this identifier to associate symbols with crash events. If this ID is missing for some reason, invoke `upload-dif` before stripping so that `sentry-cli` can compute a stable identifier from the unstripped file including debug information.

Example:

```bash
$ sentry-cli upload-dif --no-bin -t elf .
```

## Upload Options

There are a few options you can supply for the upload process

`--no-bin`

: Exclude executables and libraries from the upload and search for debug files only. Activate this setting if debug information has been stripped and moved into separate files.

`--no-debug`

: Exclude files containing only stripped debugging information. Use this option when uploading unstripped binaries to avoid using the wrong files when searching folders and archives.

`--no-zips`

: By default, sentry-cli will open and search ZIP archives for files. This is especially useful when downloading builds from iTunes Connect. Use this switch to disable if your search paths contain large ZIP archives without debug information files to speed up the search.

`--no-reprocessing`

: This parameter prevents Sentry from triggering reprocessing right away. It can be useful under rare circumstances where you want to upload files in multiple batches and you want to ensure that Sentry does not start reprocessing before some optional dsyms are uploaded. Note though that someone can still in the meantime trigger reprocessing from the UI.

repository: sanjaydatasciencedojo/sentry-docs

repo_name: sanjaydatasciencedojo/sentry-docs


text:
---
title: Airnode starter
---

# {{$frontmatter.title}}
<TocHeader />
<TOC class="table-of-contents" :include-level="[2,3]" />

> A starter project for deploying an Airnode and making requests to it

See the code [here](https://github.com/api3dao/airnode-starter/tree/pre-alpha)

This project is composed of two steps:
1. Deploy an Airnode on a supported chain
2. Make a request to the deployed Airnode in a contract

Currently supported chains:
- Ropsten
- Rinkeby
- Goerli
- xDai
- Fantom

You can skip the first step and use the Airnode that we have deployed on **Ropsten** as well.
You are recommended to read the contents of the scripts as you run them, and read the entire readme before starting.

## Setup

First, you need to create a wallet and fund it.

1. Clone this repo
2. Run the following to install the dependencies
```sh
npm install
```
3. Run the following to build the contracts
```sh
npm run build
```
4. Run the following to generate a wallet, whose mnemonic phrase will be displayed on the terminal and recorded in a `.env` file at the project root.
```sh
npm run generate-wallet
```
5. Install [Metamask](https://metamask.io/) to your web browser
6. Import the mnemonic phrase to Metamask
7. Use the [faucet](https://faucet.metamask.io/) to get some Ropsten ETH, or use any other appropriate source for the chain you will be working on

Then, you need to get a provider URL.
This will be used both by the deployed Airnode and by you while interacting with contracts.
If you will be working on Ropsten:
1.  Replace `https://ropsten.infura.io/v3/{YOUR_KEY}` in your `.env` file with the URL you got from Infura

Adapt the steps above if you will be using another chain.
Note that you can use any other provider or your own node.
However, if you will be deploying your own Airnode, the provider endpoint must be publicly accessible (i.e., `<IP_ADDRESS>:8545` will not work).

*(You only need cloud credentials if you will not be skipping Step 1.)*

Follow the [docs](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/deploying-airnode.html#creating-cloud-credentials) to create your cloud credentials.
Place them at `/config/.env`, similar to /config/example.env.
Do not confuse this `.env` file with the one in the project root that keeps your mnemonic phrase and provider URL.

**Following these instructions to deploy an Airnode on AWS is [free](https://aws.amazon.com/free/) at the time this is being written.**

## Step 1: Deploy an Airnode

Normally, you would need to do two things before you deploy an Airnode:
1. [Specify the API integration](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/api-integration.html)
1. [Configure your Airnode](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/configuring-airnode.html)

For this project, we specified a minimal integration to the popular and free [CoinGecko API](https://www.coingecko.com/en/api), and prepared the configuration files.
We only integrated a single API operation, `GET` for `/coins/{id}`, which you can see below.
The `localization`, `tickers`, `community_data`, `developer_data` and `sparkline` parameters are [fixed](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/api-integration.html#fixedoperationparameters) as `"false"`, while `market_data` is fixed as `"true"`.
The `id` parameter will be provided by the requester (e.g., `"ethereum"`) under the name `coinId`.
You can make test calls over the [CoinGecko API docs](https://www.coingecko.com/en/api) to see the response format.

See [config.example.json](config-json.md) for how this integration is achieved.
We fixed the [reserved parameters](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/api-integration.html#reservedparameters) to read the value from `market_data.current_price.usd`, cast it as an `int256` and multiply it by `1,000,000` before returning.
No security scheme (i.e., API key) is defined in `config.json` or [security.json](secrets-env.md) because the CoinGecko API is publicly accessible.

### Customize your `config.json`

Run the following to insert the contents of `.env` to `config/config.example.json` and save it as `config/config.json`
```sh
npm run customize-config
```

### Deploy

Now your `/config` directory should have the required [config.json](https://api3dao.github.io/api3-docs/pre-alpha/airnode/specifications/config-json.html), [security.json](https://api3dao.github.io/api3-docs/pre-alpha/airnode/specifications/security-json.html) and [.env](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/deploying-airnode.html#creating-cloud-credentials) files.
Run the following to deploy your node:

```sh
cd config
# The deployer has to be run in the directory where the configuration files are
docker run -it --rm \
  --env-file .env \
  --env COMMAND=deploy-first-time \
  -v $(pwd):/airnode/out \
  api3/airnode-deployer:pre-alpha
```

This will output a receipt file with the extension `.receipt.json`.

### Fund your master wallet

Run the following to send your master wallet 0.1 ETH for it to [create a provider record](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/provider.html#creating-a-provider-record) for you on-chain.
```sh
npm run fund-master-wallet
```

Your deployed Airnode will use these funds to make the transaction that will create the provider record on the chain you are operating on, and send the leftover ETH back to your address automatically.
**You will have to wait ~1 minute for this to happen, otherwise the next step will fail.**

### Make your endpoint publicly accessible

`config.json` defines an [endpoint](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/endpoint.html) named `coinMarketData`, whose [endpoint ID](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/endpoint.html#endpointid) is `0xf466b8feec41e9e50815e0c9dca4db1ff959637e564bb13fefa99e9f9f90453c`.
Endpoints are not publicly accessible by default, so you will have to make a transaction for this.
Run the following to set your endpoint's [authorizers](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/authorizer.html) to `[0x0000000000000000000000000000000000000000]`, which makes it [publicly accessible](https://api3dao.github.io/api3-docs/pre-alpha/guides/provider/setting-authorizers.html#allow-all):
```sh
npm run update-authorizers
```

## Step 2: Make a request

The scripts in this step will use the Airnode you have deployed if you have completed Step 1.
Otherwise, it will use the `airnodeId` of the Airnode that we have deployed given in `src/parameters.js`.
Note that the `endpointId` will be the same either way because it is [derived from the OIS and endpoint name](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/endpoint.html#endpointid).

### Create a requester

Run the following to create an on-chain [requester](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/requester.html) record:
```sh
npm run create-requester
```

You can use this requester denoted with an index in other projects as well.
Note that `requesterIndex` is chain-specific, so you will have to create another requester record on other chains.

### Deploy the client contract

Run the following to deploy `ExampleClient.sol`:
```sh
npm run deploy-client
```

### Endorse the client

Run the following to [endorse](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/endorsement.html) your deployed [client](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/client.html) contract using the requester you have created:
```sh
npm run endorse-client
```

### Derive and fund the designated wallet

First run the following to derive the [designated wallet](https://api3dao.github.io/api3-docs/pre-alpha/protocols/request-response/designated-wallet.html) for the provider–requester pair:
```sh
npm run derive-designated-wallet-address
```
and then fund this designated wallet with 0.1 ETH:
```sh
npm run fund-designated-wallet
```

The requests that the client contract will make will be funded by this 0.1 ETH.
Note that you may have to run `fund-designated-wallet` again if you make too many requests and use up this 0.1 ETH (very unlikely).

### Make a request

Run the following to make a request:
```
npm run make-request
```
which should be fulfilled by the Airnode and printed out on the terminal.
Note that now that the price is on-chain, you can use it in your contract to implement any arbitrary logic.

Try replacing the `coinId` value in `/scripts/make-request` from `"ethereum"` to `"bitcoin"` and make another request.
You can see the API docs to find out which coin IDs are supported.

## Conclusion

You deployed an Airnode, made a request to it and received the response at the contract.
If you want to learn more, see the following resources:

- [API3 whitepaper](https://github.com/api3dao/api3-whitepaper) will give you a broad overview of the project
- [Blog (Medium) posts](../../blog-posts.md) are a more digestible version of the whitepaper
- [@api3/airnode-admin](https://github.com/api3dao/airnode/tree/pre-alpha/packages/admin) lets you interact with the Airnode contract (to create a request, endorse a client, etc.) using a CLI tool
- [Airnode client examples](https://github.com/api3dao/airnode-client-examples/tree/pre-alpha) demonstrate different request patterns that the Airnode protocol supports (for example, we used a full request in this starter project)

## Taking down your Airnode

It is very unlikely for you to forget to take down your Airnode because it is designed to be *set-and-forget*.
When you are done with this project, go to `config/` as your working directory and use the command below where `$RECEIPT_FILENAME` is replaced with the name of your receipt file ending with `.receipt.json` (you can refer to our [Docker instructions](https://github.com/api3dao/airnode/blob/pre-alpha/Docker.md) for more information)

```sh
docker run -it --rm \
  --env-file .env \
  --env COMMAND=remove-with-receipt \
  --env RECEIPT_FILENAME=$RECEIPT_FILENAME \
  -v $(pwd):/airnode/out \
  api3/airnode-deployer:pre-alpha
```


text:
# Keep-alive

Provides keep-alive (reconnects if connection drops) GATT communication.

## Structured Concurrency

A keep-alive GATT is created by calling the `keepAliveGatt` extension function on
[`CoroutineScope`], which has the following signature:

```kotlin
fun CoroutineScope.keepAliveGatt(
    androidContext: Context,
    bluetoothDevice: BluetoothDevice,
    disconnectTimeoutMillis: Long
): KeepAliveGatt
```

| Parameter                 | Description                                                                                |
|---------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `androidContext`          | The Android `Context` for establishing Bluetooth Low-Energy connections.                                                  |
| `bluetoothDevice`         | `BluetoothDevice` to maintain a connection with.                                                                          |
| `disconnectTimeoutMillis` | Duration (in milliseconds) to wait for connection to gracefully spin down (after `disconnect`) before forcefully closing. |

For example, to create a `KeepAliveGatt` as a child of Android's `viewModelScope`:

```kotlin
class ExampleViewModel(application: Application) : AndroidViewModel(application) {

    private const val MAC_ADDRESS = ...

    private val gatt = viewModelScope.keepAliveGatt(
        application,
        bluetoothAdapter.getRemoteDevice(MAC_ADDRESS),
        disconnectTimeoutMillis = 5_000L // 5 seconds
    )

    fun connect() {
        gatt.connect()
    }
}
```

When the parent [`CoroutineScope`] (`viewModelScope` in the above example) cancels, the
`KeepAliveGatt` also cancels (and disconnects).

When cancelled, a `KeepAliveGatt` will end in a `Cancelled` state. Once a `KeepAliveGatt` is
`Cancelled` it **cannot** be reconnected (calls to `connect` will throw `IllegalStateException`); a
new `KeepAliveGatt` must be created.

## Connection Handling

A `KeepAliveGatt` will start in a `Disconnected` state. When `connect` is called, `KeepAliveGatt`
will attempt to establish a connection (`Connecting`). If the connection is rejected (e.g. BLE is
turned off), then `KeepAliveGatt` will settle at `Disconnected` state. The `connect` function can be
called again to re-attempt to establish a connection:

![Connection rejected](artwork/connect-reject.png)

If a connection cannot be established (e.g. BLE device out-of-range) then `KeepAliveGatt` will retry
indefinitely:

![Connection failure](artwork/connect-failure.png)

Once `Connected`, if the connection drops, then `KeepAliveGatt` will automatically reconnect:

![Reconnect on connection drop](artwork/connection-drop.png)

_To disconnect an established connection or cancel an in-flight connection attempt, `disconnect` can
be called (it will suspend until underlying [`BluetoothGatt`] has disconnected)._

## Status

The status of a `KeepAliveGatt` can be monitored via either `Event`s or `State`s. The major
distinction between the two is:

> **`State`**: `State`s are propagated over conflated data streams. If states are changing quickly,
> then some `State`s may be missed (skipped over). For this reason, they're useful for informing a
> user of the current state of the connection; as missing a state is acceptable since subsequent
> states will overwrite the currently reflected state anyways. `State`s should **not** be used if a
> specific condition (e.g. `Connected`) needs to trigger an action (use `Event` instead).

> **`Event`**: `Event`s allow a developer to integrate actions into the connection process. If
> consumers are slow to `collect` events, then the connection handling process pauses (suspends)
> until consumers are ready to `collect` more events.

`State`s and `Event`s occur in the following order:

![State and event flow](artwork/state-and-event-flow.png)

### Events

`Event`s can be `collect`ed via the `events` `Flow`, for example:

```kotlin
val keepAliveGatt = GlobalScope.keepAliveGatt(...)

viewModelScope.launch {
    keepAliveGatt.events.collect { event ->
        event.onConnected {
            // Actions to perform on initial connect *and* subsequent reconnects:
            discoverServicesOrThrow()
        }
        event.onDisconnected {
            // todo: retry strategy (e.g. exponentially increasing delay)
        }
    }
}
```

For example, if is desired to retry connection if a failure occurs while setting up a connection,
simply call `disconnect()` and `KeepAliveGatt` will (as usual) attempt to reconnect the lost
connection:

```kotlin
keepAliveGatt.events.collect { event ->
    event.onConnected { // `this` is the underlying `Gatt`.
        try {
            // todo: On connect actions.
        } catch (e: Exception) {
            disconnect() // Instructs underlying Gatt to disconnect.
            // KeepAliveGatt will react by attempting another connection.
        }
    }
}
```

Alternatively, if you want to cancel the connection process (and settle on a `Disconnect` state) you
can instruct the `KeepAliveGatt` to `disconnect()`:

```kotlin
keepAliveGatt.events.collect { event ->
    event.onConnected {
        try {
            // todo: On connect actions.
        } catch (e: Exception) {
            keepAliveGatt.disconnect() // Instructs `KeepAliveGatt` to settle on a `Disconnected` state.
        }
    }
}
```

### State

Connection state can be monitored via the `state` [`Flow`] property:

```kotlin
val gatt = scope.keepAliveGatt(...)
gatt.state.collect { println("State: $it") }
```

## I/O

If a Gatt operation (e.g. `discoverServices`, `writeCharacteristic`, `readCharacteristic`, etc) is
unable to be performed due to a GATT connection being unavailable (i.e. current `State` is **not**
`Connected`), then it will immediately throw `NotReadyException`.

It is the responsibility of the caller to handle retrying, for example:

```kotlin
class GattCancelledException : Exception()

suspend fun KeepAliveGatt.readCharacteristicWithRetry(
    characteristic: BluetoothGattCharacteristic,
    retryCount: Int = Int.MAX_VALUE
): OnCharacteristicRead {
    repeat(retryCount) {
        suspendUntilConnected()
        try {
            return readCharacteristicOrThrow(characteristic)
        } catch (exception: Exception) {
            // todo: retry strategy (e.g. exponentially increasing delay)
        }
    }
    error("Failed to read characteristic $characteristic")
}

private suspend fun KeepAliveGatt.suspendUntilConnected() {
    state
        .onEach { if (it is Cancelled) throw GattCancelledException() }
        .first { it == Connected }
}
```

### Characteristic Changes

When a `KeepAliveGatt` is created, it immediately provides a [`Flow`] for incoming characteristic
changes (`onCharacteristicChange` property). The [`Flow`] is a hot stream, so characteristic change
events emitted before subscribers have subscribed are dropped. To prevent characteristic change
events from being lost, be sure to setup subscribers **before** calling `KeepAliveGatt.connect`, for
example:

```kotlin
val gatt = scope.keepAliveGatt(...)

fun connect() {
    // `CoroutineStart.UNDISPATCHED` executes within `launch` up to the `collect` (then suspends),
    // before allowing continued execution of `gatt.connect()` (below).
    launch(start = CoroutineStart.UNDISPATCHED) {
        gatt.onCharacteristicChange.collect {
            println("Characteristic changed: $it")
        }
    }

    gatt.connect()
}
```

If the underlying [`BluetoothGatt`] connection is dropped, the characteristic change event stream
remains open (and all subscriptions will continue to `collect`). When a new [`BluetoothGatt`]
connection is established, all it's characteristic change events are automatically routed to the
existing subscribers of the `KeepAliveGatt`.

## Error Handling

When connection failures occur, the corresponding `Exception`s are propagated to `KeepAliveGatt`'s
parent [`CoroutineScope`] and can be inspected via [`CoroutineExceptionHandler`]:

```kotlin
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
    println(throwable)
}
val scope = CoroutineScope(Job() + exceptionHandler)
val gatt = scope.keepAliveGatt(...)
```

# Setup

## Gradle

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.juul.able/keep-alive/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.juul.able/keep-alive)

```groovy
repositories {
    jcenter() // or mavenCentral()
}

dependencies {
    implementation "com.juul.able:keep-alive:$version"
}
```

[`BluetoothDevice.connectGatt`]: https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)
[`BluetoothGatt`]: https://developer.android.com/reference/android/bluetooth/BluetoothGatt
[`CoroutineScope`]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/
[`CoroutineContext`]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/
[`Flow`]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
[`CoroutineExceptionHandler`]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/

repository: quine/able

repo_name: quine/able