Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
298 changed files with 5726 additions and 77955 deletions
33
.gitignore
vendored
33
.gitignore
vendored
|
@ -1,33 +0,0 @@
|
||||||
prototype/chain-manager/patch.*
|
|
||||||
.eqc-info
|
|
||||||
.eunit
|
|
||||||
deps
|
|
||||||
dev
|
|
||||||
erl_crash.dump
|
|
||||||
eqc
|
|
||||||
.concrete/DEV_MODE
|
|
||||||
.rebar
|
|
||||||
edoc
|
|
||||||
|
|
||||||
# Dialyzer stuff
|
|
||||||
.dialyzer-last-run.txt
|
|
||||||
.ebin.native
|
|
||||||
.local_dialyzer_plt
|
|
||||||
dialyzer_unhandled_warnings
|
|
||||||
dialyzer_warnings
|
|
||||||
*.plt
|
|
||||||
|
|
||||||
# PB artifacts for Erlang
|
|
||||||
include/machi_pb.hrl
|
|
||||||
|
|
||||||
# Release packaging
|
|
||||||
rel/machi
|
|
||||||
rel/vars/dev*vars.config
|
|
||||||
|
|
||||||
# Misc Scott cruft
|
|
||||||
*.patch
|
|
||||||
current_counterexample.eqc
|
|
||||||
foo*
|
|
||||||
RUNLOG*
|
|
||||||
typescript*
|
|
||||||
*.swp
|
|
|
@ -1,7 +0,0 @@
|
||||||
language: erlang
|
|
||||||
notifications:
|
|
||||||
email: scott@basho.com
|
|
||||||
script: "priv/test-for-gh-pr.sh"
|
|
||||||
otp_release:
|
|
||||||
- 17.5
|
|
||||||
## No, Dialyzer is too different between 17 & 18: - 18.1
|
|
|
@ -1,35 +0,0 @@
|
||||||
# Contributing to the Machi project
|
|
||||||
|
|
||||||
The most helpful way to contribute is by reporting your experience
|
|
||||||
through issues. Issues may not be updated while we review internally,
|
|
||||||
but they're still incredibly appreciated.
|
|
||||||
|
|
||||||
Pull requests may take multiple engineers for verification and testing. If
|
|
||||||
you're passionate enough to want to learn more on how you can get
|
|
||||||
hands on in this process, reach out to
|
|
||||||
[Matt Brender](mailto:mbrender@basho.com), your developer advocate.
|
|
||||||
|
|
||||||
Thank you for being part of the community! We love you for it.
|
|
||||||
|
|
||||||
## If you have a question or wish to provide design feedback/criticism
|
|
||||||
|
|
||||||
Please
|
|
||||||
[open a support ticket at GitHub](https://github.com/basho/machi/issues/new)
|
|
||||||
to ask questions and to provide feedback about Machi's
|
|
||||||
design/documentation/source code.
|
|
||||||
|
|
||||||
## General development process
|
|
||||||
|
|
||||||
Machi is still a very young project within Basho, with a small team of
|
|
||||||
developers; please bear with us as we grow out of "toddler" stage into
|
|
||||||
a more mature open source software project.
|
|
||||||
|
|
||||||
* Fork the Machi source repo and/or the sub-projects that are affected
|
|
||||||
by your change.
|
|
||||||
* Create a topic branch for your change and checkout that branch.
|
|
||||||
git checkout -b some-topic-branch
|
|
||||||
* Make your changes and run the test suite if one is provided.
|
|
||||||
* Commit your changes and push them to your fork.
|
|
||||||
* Open pull-requests for the appropriate projects.
|
|
||||||
* Contributors will review your pull request, suggest changes, and merge it when it’s ready and/or offer feedback.
|
|
||||||
* To report a bug or issue, please open a new issue against this repository.
|
|
630
FAQ.md
630
FAQ.md
|
@ -1,630 +0,0 @@
|
||||||
# Frequently Asked Questions (FAQ)
|
|
||||||
|
|
||||||
<!-- Formatting: -->
|
|
||||||
<!-- All headings omitted from outline are H1 -->
|
|
||||||
<!-- All other headings must be on a single line! -->
|
|
||||||
<!-- Run: ./priv/make-faq.pl ./FAQ.md > ./tmpfoo; mv ./tmpfoo ./FAQ.md -->
|
|
||||||
|
|
||||||
# Outline
|
|
||||||
|
|
||||||
<!-- OUTLINE -->
|
|
||||||
|
|
||||||
+ [1 Questions about Machi in general](#n1)
|
|
||||||
+ [1.1 What is Machi?](#n1.1)
|
|
||||||
+ [1.2 What is a Machi chain?](#n1.2)
|
|
||||||
+ [1.3 What is a Machi cluster?](#n1.3)
|
|
||||||
+ [1.4 What is Machi like when operating in "eventually consistent" mode?](#n1.4)
|
|
||||||
+ [1.5 What is Machi like when operating in "strongly consistent" mode?](#n1.5)
|
|
||||||
+ [1.6 What does Machi's API look like?](#n1.6)
|
|
||||||
+ [1.7 What licensing terms are used by Machi?](#n1.7)
|
|
||||||
+ [1.8 Where can I find the Machi source code and documentation? Can I contribute?](#n1.8)
|
|
||||||
+ [1.9 What is Machi's expected release schedule, packaging, and operating system/OS distribution support?](#n1.9)
|
|
||||||
+ [2 Questions about Machi relative to {{something else}}](#n2)
|
|
||||||
+ [2.1 How is Machi better than Hadoop?](#n2.1)
|
|
||||||
+ [2.2 How does Machi differ from HadoopFS/HDFS?](#n2.2)
|
|
||||||
+ [2.3 How does Machi differ from Kafka?](#n2.3)
|
|
||||||
+ [2.4 How does Machi differ from Bookkeeper?](#n2.4)
|
|
||||||
+ [2.5 How does Machi differ from CORFU and Tango?](#n2.5)
|
|
||||||
+ [3 Machi's specifics](#n3)
|
|
||||||
+ [3.1 What technique is used to replicate Machi's files? Can other techniques be used?](#n3.1)
|
|
||||||
+ [3.2 Does Machi have a reliance on a coordination service such as ZooKeeper or etcd?](#n3.2)
|
|
||||||
+ [3.3 Are there any presentations available about Humming Consensus](#n3.3)
|
|
||||||
+ [3.4 Is it true that there's an allegory written to describe Humming Consensus?](#n3.4)
|
|
||||||
+ [3.5 How is Machi tested?](#n3.5)
|
|
||||||
+ [3.6 Does Machi require shared disk storage? e.g. iSCSI, NBD (Network Block Device), Fibre Channel disks](#n3.6)
|
|
||||||
+ [3.7 Does Machi require or assume that servers with large numbers of disks must use RAID-0/1/5/6/10/50/60 to create a single block device?](#n3.7)
|
|
||||||
+ [3.8 What language(s) is Machi written in?](#n3.8)
|
|
||||||
+ [3.9 Can Machi run on Windows? Can Machi run on 32-bit platforms?](#n3.9)
|
|
||||||
+ [3.10 Does Machi use the Erlang/OTP network distribution system (aka "disterl")?](#n3.10)
|
|
||||||
+ [3.11 Can I use HTTP to write/read stuff into/from Machi?](#n3.11)
|
|
||||||
|
|
||||||
<!-- ENDOUTLINE -->
|
|
||||||
|
|
||||||
<a name="n1">
|
|
||||||
## 1. Questions about Machi in general
|
|
||||||
|
|
||||||
<a name="n1.1">
|
|
||||||
### 1.1. What is Machi?
|
|
||||||
|
|
||||||
Very briefly, Machi is a very simple append-only blob/file store.
|
|
||||||
|
|
||||||
Machi is
|
|
||||||
"dumber" than many other file stores (i.e., lacking many features
|
|
||||||
found in other file stores) such as HadoopFS or a simple NFS or CIFS file
|
|
||||||
server.
|
|
||||||
However, Machi is a distributed blob/file store, which makes it different
|
|
||||||
(and, in some ways, more complicated) than a simple NFS or CIFS file
|
|
||||||
server.
|
|
||||||
|
|
||||||
All Machi data is protected by SHA-1 checksums. By default, these
|
|
||||||
checksums are calculated by the client to provide strong end-to-end
|
|
||||||
protection against data corruption. (If the client does not provide a
|
|
||||||
checksum, one will be generated by the first Machi server to handle
|
|
||||||
the write request.) Internally, Machi uses these checksums for local
|
|
||||||
data integrity checks and for server-to-server file synchronization
|
|
||||||
and corrupt data repair.
|
|
||||||
|
|
||||||
As a distributed system, Machi can be configured to operate with
|
|
||||||
either eventually consistent mode or strongly consistent mode. In
|
|
||||||
strongly consistent mode, Machi can provide write-once file store
|
|
||||||
service in the same style as CORFU. Machi can be an easy to use tool
|
|
||||||
for building fully ordered, log-based distributed systems and
|
|
||||||
distributed data structures.
|
|
||||||
|
|
||||||
In eventually consistent mode, Machi can remain available for writes
|
|
||||||
during arbitrary network partitions. When a network partition is
|
|
||||||
fixed, Machi can safely merge all file data together without data
|
|
||||||
loss. Similar to the operation of
|
|
||||||
Basho's
|
|
||||||
[Riak key-value store, Riak KV](http://basho.com/products/riak-kv/),
|
|
||||||
Machi can provide file writes during arbitrary network partitions and
|
|
||||||
later merge all results together safely when the cluster recovers.
|
|
||||||
|
|
||||||
For a much longer answer, please see the
|
|
||||||
[Machi high level design doc](https://github.com/basho/machi/tree/master/doc/high-level-machi.pdf).
|
|
||||||
|
|
||||||
<a name="n1.2">
|
|
||||||
### 1.2. What is a Machi chain?
|
|
||||||
|
|
||||||
A Machi chain is a small number of machines that maintain a common set
|
|
||||||
of replicated files. A typical chain is of length 2 or 3. For
|
|
||||||
critical data that must be available despite several simultaneous
|
|
||||||
server failures, a chain length of 6 or 7 might be used.
|
|
||||||
|
|
||||||
<a name="n1.3">
|
|
||||||
### 1.3. What is a Machi cluster?
|
|
||||||
|
|
||||||
A Machi cluster is a collection of Machi chains that
|
|
||||||
partitions/shards/distributes files (based on file name) across the
|
|
||||||
collection of chains. Machi uses the "random slicing" algorithm (a
|
|
||||||
variation of consistent hashing) to define the mapping of file name to
|
|
||||||
chain name.
|
|
||||||
|
|
||||||
The cluster management service will be fully decentralized
|
|
||||||
and run as a separate software service installed on each Machi
|
|
||||||
cluster. This manager will appear to the local Machi server as simply
|
|
||||||
another Machi file client. The cluster managers will take
|
|
||||||
care of file migration as the cluster grows and shrinks in capacity
|
|
||||||
and in response to day-to-day changes in workload.
|
|
||||||
|
|
||||||
Though the cluster manager has not yet been implemented,
|
|
||||||
its design is fully decentralized and capable of operating despite
|
|
||||||
multiple partial failure of its member chains. We expect this
|
|
||||||
design to scale easily to at least one thousand servers.
|
|
||||||
|
|
||||||
Please see the
|
|
||||||
[Machi source repository's 'doc' directory for more details](https://github.com/basho/machi/tree/master/doc/).
|
|
||||||
|
|
||||||
<a name="n1.4">
|
|
||||||
### 1.4. What is Machi like when operating in "eventually consistent" mode?
|
|
||||||
|
|
||||||
Machi's operating mode dictates how a Machi cluster will react to
|
|
||||||
network partitions. A network partition may be caused by:
|
|
||||||
|
|
||||||
* A network failure
|
|
||||||
* A server failure
|
|
||||||
* An extreme server software "hang" or "pause", e.g. caused by OS
|
|
||||||
scheduling problems such as a failing/stuttering disk device.
|
|
||||||
|
|
||||||
The consistency semantics of file operations while in eventual
|
|
||||||
consistency mode during and after network partitions are:
|
|
||||||
|
|
||||||
* File write operations are permitted by any client on the "same side"
|
|
||||||
of the network partition.
|
|
||||||
* File read operations are successful for any file contents where the
|
|
||||||
client & server are on the "same side" of the network partition.
|
|
||||||
* File read operations will probably fail for any file contents where the
|
|
||||||
client & server are on "different sides" of the network partition.
|
|
||||||
* After the network partition(s) is resolved, files are merged
|
|
||||||
together from "all sides" of the partition(s).
|
|
||||||
* Unique files are copied in their entirety.
|
|
||||||
* Byte ranges within the same file are merged. This is possible
|
|
||||||
due to Machi's restrictions on file naming and file offset
|
|
||||||
assignment. Both file names and file offsets are always chosen
|
|
||||||
by Machi servers according to rules which guarantee safe
|
|
||||||
mergeability. Server-assigned names are a characteristic of a
|
|
||||||
"blob store".
|
|
||||||
|
|
||||||
<a name="n1.5">
|
|
||||||
### 1.5. What is Machi like when operating in "strongly consistent" mode?
|
|
||||||
|
|
||||||
The consistency semantics of file operations while in strongly
|
|
||||||
consistency mode during and after network partitions are:
|
|
||||||
|
|
||||||
* File write operations are permitted by any client on the "same side"
|
|
||||||
of the network partition if and only if a quorum majority of Machi servers
|
|
||||||
are also accessible within that partition.
|
|
||||||
* In other words, file write service is unavailable in any
|
|
||||||
partition where only a minority of Machi servers are accessible.
|
|
||||||
* File read operations are successful for any file contents where the
|
|
||||||
client & server are on the "same side" of the network partition.
|
|
||||||
* After the network partition(s) is resolved, files are repaired from
|
|
||||||
the surviving quorum majority members to out-of-sync minority
|
|
||||||
members.
|
|
||||||
|
|
||||||
Machi's design can provide the illusion of quorum minority write
|
|
||||||
availability if the cluster is configured to operate with "witness
|
|
||||||
servers". (This feaure partially implemented, as of December 2015.)
|
|
||||||
See Section 11 of
|
|
||||||
[Machi chain manager high level design doc](https://github.com/basho/machi/tree/master/doc/high-level-chain-mgr.pdf)
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
<a name="n1.6">
|
|
||||||
### 1.6. What does Machi's API look like?
|
|
||||||
|
|
||||||
The Machi API only contains a handful of API operations. The function
|
|
||||||
arguments shown below (in simplifed form) use Erlang-style type annotations.
|
|
||||||
|
|
||||||
append_chunk(Prefix:binary(), Chunk:binary(), CheckSum:binary()).
|
|
||||||
append_chunk_extra(Prefix:binary(), Chunk:binary(), CheckSum:binary(), ExtraSpace:non_neg_integer()).
|
|
||||||
read_chunk(File:binary(), Offset:non_neg_integer(), Size:non_neg_integer()).
|
|
||||||
|
|
||||||
checksum_list(File:binary()).
|
|
||||||
list_files().
|
|
||||||
|
|
||||||
Machi allows the client to choose the prefix of the file name to
|
|
||||||
append data to, but the Machi server will always choose the final file
|
|
||||||
name and byte offset for each `append_chunk()` operation. This
|
|
||||||
restriction on file naming makes it easy to operate in "eventually
|
|
||||||
consistent" mode: files may be written to any server during network
|
|
||||||
partitions and can be easily merged together after the partition is
|
|
||||||
healed.
|
|
||||||
|
|
||||||
Internally, there is a more complex protocol used by individual
|
|
||||||
cluster members to manage file contents and to repair damaged/missing
|
|
||||||
files. See Figure 3 in
|
|
||||||
[Machi high level design doc](https://github.com/basho/machi/tree/master/doc/high-level-machi.pdf)
|
|
||||||
for more description.
|
|
||||||
|
|
||||||
The definitions of both the "high level" external protocol and "low
|
|
||||||
level" internal protocol are in a
|
|
||||||
[Protocol Buffers](https://developers.google.com/protocol-buffers/docs/overview)
|
|
||||||
definition at [./src/machi.proto](./src/machi.proto).
|
|
||||||
|
|
||||||
<a name="n1.7">
|
|
||||||
### 1.7. What licensing terms are used by Machi?
|
|
||||||
|
|
||||||
All Machi source code and documentation is licensed by
|
|
||||||
[Basho Technologies, Inc.](http://www.basho.com/)
|
|
||||||
under the [Apache Public License version 2](https://github.com/basho/machi/tree/master/LICENSE).
|
|
||||||
|
|
||||||
<a name="n1.8">
|
|
||||||
### 1.8. Where can I find the Machi source code and documentation? Can I contribute?
|
|
||||||
|
|
||||||
All Machi source code and documentation can be found at GitHub:
|
|
||||||
[https://github.com/basho/machi](https://github.com/basho/machi).
|
|
||||||
The full URL for this FAQ is [https://github.com/basho/machi/blob/master/FAQ.md](https://github.com/basho/machi/blob/master/FAQ.md).
|
|
||||||
|
|
||||||
There are several "README" files in the source repository. We hope
|
|
||||||
they provide useful guidance for first-time readers.
|
|
||||||
|
|
||||||
If you're interested in contributing code or documentation or
|
|
||||||
ideas for improvement, please see our contributing & collaboration
|
|
||||||
guidelines at
|
|
||||||
[https://github.com/basho/machi/blob/master/CONTRIBUTING.md](https://github.com/basho/machi/blob/master/CONTRIBUTING.md).
|
|
||||||
|
|
||||||
<a name="n1.9">
|
|
||||||
### 1.9. What is Machi's expected release schedule, packaging, and operating system/OS distribution support?
|
|
||||||
|
|
||||||
Basho expects that Machi's first major product release will take place
|
|
||||||
during the 2nd quarter of 2016.
|
|
||||||
|
|
||||||
Basho's official support for operating systems (e.g. Linux, FreeBSD),
|
|
||||||
operating system packaging (e.g. CentOS rpm/yum package management,
|
|
||||||
Ubuntu debian/apt-get package management), and
|
|
||||||
container/virtualization have not yet been chosen. If you wish to
|
|
||||||
provide your opinion, we'd love to hear it. Please
|
|
||||||
[open a support ticket at GitHub](https://github.com/basho/machi/issues/new)
|
|
||||||
and let us know.
|
|
||||||
|
|
||||||
<a name="n2">
|
|
||||||
## 2. Questions about Machi relative to {{something else}}
|
|
||||||
|
|
||||||
<a name="better-than-hadoop">
|
|
||||||
<a name="n2.1">
|
|
||||||
### 2.1. How is Machi better than Hadoop?
|
|
||||||
|
|
||||||
This question is frequently asked by trolls. If this is a troll
|
|
||||||
question, the answer is either, "Nothing is better than Hadoop," or
|
|
||||||
else "Everything is better than Hadoop."
|
|
||||||
|
|
||||||
The real answer is that Machi is not a distributed data processing
|
|
||||||
framework like Hadoop is.
|
|
||||||
See [Hadoop's entry in Wikipedia](https://en.wikipedia.org/wiki/Apache_Hadoop)
|
|
||||||
and focus on the description of Hadoop's MapReduce and YARN; Machi
|
|
||||||
contains neither.
|
|
||||||
|
|
||||||
<a name="n2.2">
|
|
||||||
### 2.2. How does Machi differ from HadoopFS/HDFS?
|
|
||||||
|
|
||||||
This is a much better question than the
|
|
||||||
[How is Machi better than Hadoop?](#better-than-hadoop)
|
|
||||||
question.
|
|
||||||
|
|
||||||
[HadoopFS's entry in Wikipedia](https://en.wikipedia.org/wiki/Apache_Hadoop#HDFS)
|
|
||||||
|
|
||||||
One way to look at Machi is to consider Machi as a distributed file
|
|
||||||
store. HadoopFS is also a distributed file store. Let's compare and
|
|
||||||
contrast.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> <b>Machi</b>
|
|
||||||
<td> <b>HadoopFS (HDFS)</b>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Not POSIX compliant
|
|
||||||
<td> Not POSIX compliant
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Immutable file store with append-only semantics (simplifying
|
|
||||||
things a little bit).
|
|
||||||
<td> Immutable file store with append-only semantics
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> File data may be read concurrently while file is being actively
|
|
||||||
appended to.
|
|
||||||
<td> File must be closed before a client can read it.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> No concept (yet) of users or authentication (though the initial
|
|
||||||
supported release will support basic user + password authentication).
|
|
||||||
Machi will probably never natively support directories or ACLs.
|
|
||||||
<td> Has concepts of users, directories, and ACLs.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Machi does not allow clients to name their own files or to specify data
|
|
||||||
placement/offset within a file.
|
|
||||||
<td> While not POSIX compliant, HDFS allows a fairly flexible API for
|
|
||||||
managing file names and file writing position within a file (during a
|
|
||||||
file's writable phase).
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Does not have any file distribution/partitioning/sharding across
|
|
||||||
Machi chains: in a single Machi chain, all files are replicated by
|
|
||||||
all servers in the chain. The "random slicing" technique is used
|
|
||||||
to distribute/partition/shard files across multiple Machi clusters.
|
|
||||||
<td> File distribution/partitioning/sharding is performed
|
|
||||||
automatically by the HDFS "name node".
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Machi requires no central "name node" for single chain use or
|
|
||||||
for multi-chain cluster use.
|
|
||||||
<td> Requires a single "namenode" server to maintain file system contents
|
|
||||||
and file content mapping. (May be deployed with a "secondary
|
|
||||||
namenode" to reduce unavailability when the primary namenode fails.)
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Machi uses Chain Replication to manage all file replicas.
|
|
||||||
<td> The HDFS name node uses an ad hoc mechanism for replicating file
|
|
||||||
contents. The HDFS file system metadata (file names, file block(s)
|
|
||||||
locations, ACLs, etc.) is stored by the name node in the local file
|
|
||||||
system and is replicated to any secondary namenode using snapshots.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Machi replicates files *N* ways where *N* is the length of the
|
|
||||||
Chain Replication chain. Typically, *N=2*, but this is configurable.
|
|
||||||
<td> HDFS typical replicates file contents *N=3* ways, but this is
|
|
||||||
configurable.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> All Machi file data is protected by SHA-1 checksums generated by
|
|
||||||
the client prior to writing by Machi servers.
|
|
||||||
<td> Optional file checksum protection may be implemented on the
|
|
||||||
server side.
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<a name="n2.3">
|
|
||||||
### 2.3. How does Machi differ from Kafka?
|
|
||||||
|
|
||||||
Machi is rather close to Kafka in spirit, though its implementation is
|
|
||||||
quite different.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> <b>Machi</b>
|
|
||||||
<td> <b>Kafka</b>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Append-only, strongly consistent file store only
|
|
||||||
<td> Append-only, strongly consistent log file store + additional
|
|
||||||
services: for example, producer topics & sharding, consumer groups &
|
|
||||||
failover, etc.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Not yet code complete nor "battle tested" in large production
|
|
||||||
environments.
|
|
||||||
<td> "Battle tested" in large production environments.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> All Machi file data is protected by SHA-1 checksums generated by
|
|
||||||
the client prior to writing by Machi servers.
|
|
||||||
<td> Each log entry is protected by a 32 bit CRC checksum.
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
In theory, it should be "quite straightforward" to remove these parts
|
|
||||||
of Kafka's code base:
|
|
||||||
|
|
||||||
* local file system I/O for all topic/partition/log files
|
|
||||||
* leader/follower file replication, ISR ("In Sync Replica") state
|
|
||||||
management, and related log file replication logic
|
|
||||||
|
|
||||||
... and replace those parts with Machi client API calls. Those parts
|
|
||||||
of Kafka are what Machi has been designed to do from the very
|
|
||||||
beginning.
|
|
||||||
|
|
||||||
See also:
|
|
||||||
<a href="#corfu-and-tango">How does Machi differ from CORFU and Tango?</a>
|
|
||||||
|
|
||||||
<a name="n2.4">
|
|
||||||
### 2.4. How does Machi differ from Bookkeeper?
|
|
||||||
|
|
||||||
Sorry, we haven't studied Bookkeeper very deeply or used Bookkeeper
|
|
||||||
for any non-trivial project.
|
|
||||||
|
|
||||||
One notable limitation of the Bookkeeper API is that a ledger cannot
|
|
||||||
be read by other clients until it has been closed. Any byte in a
|
|
||||||
Machi file that has been written successfully may
|
|
||||||
be read immedately by any other Machi client.
|
|
||||||
|
|
||||||
The name "Machi" does not have three consecutive pairs of repeating
|
|
||||||
letters. The name "Bookkeeper" does.
|
|
||||||
|
|
||||||
<a name="corfu-and-tango">
|
|
||||||
<a name="n2.5">
|
|
||||||
### 2.5. How does Machi differ from CORFU and Tango?
|
|
||||||
|
|
||||||
Machi's design borrows very heavily from CORFU. We acknowledge a deep
|
|
||||||
debt to the original Microsoft Research papers that describe CORFU's
|
|
||||||
original design and implementation.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> <b>Machi</b>
|
|
||||||
<td> <b>CORFU</b>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Writes & reads may be on byte boundaries
|
|
||||||
<td> Wries & reads must be on page boundaries, e.g. 4 or 8 KBytes, to
|
|
||||||
align with server storage based on flash NVRAM/solid state disk (SSD).
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Provides multiple "logs", where each log has a name and is
|
|
||||||
appended to & read from like a file. A read operation requires a 3-tuple:
|
|
||||||
file name, starting byte offset, number of bytes.
|
|
||||||
<td> Provides a single "log". A read operation requires only a
|
|
||||||
1-tuple: the log page number. (A protocol option exists to
|
|
||||||
request multiple pages in a single read query?)
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> Offers service in either strongly consistent mode or eventually
|
|
||||||
consistent mode.
|
|
||||||
<td> Offers service in strongly consistent mode.
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> May be deployed on solid state disk (SSD) or Winchester hard disks.
|
|
||||||
<td> Designed for use with solid state disk (SSD) but can also be used
|
|
||||||
with Winchester hard disks (with a performance penalty if used as
|
|
||||||
suggested by use cases described by the CORFU papers).
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td> All Machi file data is protected by SHA-1 checksums generated by
|
|
||||||
the client prior to writing by Machi servers.
|
|
||||||
<td> Depending on server & flash device capabilities, each data page
|
|
||||||
may be protected by a checksum (calculated independently by each
|
|
||||||
server rather than the client).
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
See also: the "Recommended reading & related work" and "References"
|
|
||||||
sections of the
|
|
||||||
[Machi high level design doc](https://github.com/basho/machi/tree/master/doc/high-level-machi.pdf)
|
|
||||||
for pointers to the MSR papers related to CORFU.
|
|
||||||
|
|
||||||
Machi does not implement Tango directly. (Not yet, at least.)
|
|
||||||
However, there is a prototype implementation included in the Machi
|
|
||||||
source tree. See
|
|
||||||
[the prototype/tango source code directory](https://github.com/basho/machi/tree/master/prototype/tango)
|
|
||||||
for details.
|
|
||||||
|
|
||||||
Also, it's worth adding that the original MSR code behind the research
|
|
||||||
papers is now available at GitHub:
|
|
||||||
[https://github.com/CorfuDB/CorfuDB](https://github.com/CorfuDB/CorfuDB).
|
|
||||||
|
|
||||||
<a name="n3">
|
|
||||||
## 3. Machi's specifics
|
|
||||||
|
|
||||||
<a name="n3.1">
|
|
||||||
### 3.1. What technique is used to replicate Machi's files? Can other techniques be used?
|
|
||||||
|
|
||||||
Machi uses Chain Replication to replicate all file data. Each byte of
|
|
||||||
a file is stored using a "write-once register", which is a mechanism
|
|
||||||
to enforce immutability after the byte has been written exactly once.
|
|
||||||
|
|
||||||
In order to ensure availability in the event of *F* failures, Chain
|
|
||||||
Replication requires a minimum of *F + 1* servers to be configured.
|
|
||||||
|
|
||||||
Alternative mechanisms could be used to manage file replicas, such as
|
|
||||||
Paxos or Raft. Both Paxos and Raft have some requirements that are
|
|
||||||
difficult to adapt to Machi's design goals:
|
|
||||||
|
|
||||||
* Both protocols use quorum majority consensus, which requires a
|
|
||||||
minimum of *2F + 1* working servers to tolerate *F* failures. For
|
|
||||||
example, to tolerate 2 server failures, quorum majority protocols
|
|
||||||
require a minimum of 5 servers. To tolerate the same number of
|
|
||||||
failures, Chain Replication requires a minimum of only 3 servers.
|
|
||||||
* Machi's use of "humming consensus" to manage internal server
|
|
||||||
metadata state would also (probably) require conversion to Paxos or
|
|
||||||
Raft. (Or "outsourced" to a service such as ZooKeeper.)
|
|
||||||
|
|
||||||
<a name="n3.2">
|
|
||||||
### 3.2. Does Machi have a reliance on a coordination service such as ZooKeeper or etcd?
|
|
||||||
|
|
||||||
No. Machi maintains critical internal cluster information in an
|
|
||||||
internal, immutable data service called the "projection store". The
|
|
||||||
contents of the projection store are maintained by a new technique
|
|
||||||
called "humming consensus".
|
|
||||||
|
|
||||||
Humming consensus is described in the
|
|
||||||
[Machi chain manager high level design doc](https://github.com/basho/machi/tree/master/doc/high-level-chain-mgr.pdf).
|
|
||||||
|
|
||||||
<a name="n3.3">
|
|
||||||
### 3.3. Are there any presentations available about Humming Consensus
|
|
||||||
|
|
||||||
Scott recently (November 2015) gave a presentation at the
|
|
||||||
[RICON 2015 conference](http://ricon.io) about one of the techniques
|
|
||||||
used by Machi; "Managing Chain Replication Metadata with
|
|
||||||
Humming Consensus" is available online now.
|
|
||||||
* [slides (PDF format)](http://ricon.io/speakers/slides/Scott_Fritchie_Ricon_2015.pdf)
|
|
||||||
* [video](https://www.youtube.com/watch?v=yR5kHL1bu1Q)
|
|
||||||
|
|
||||||
<a name="n3.4">
|
|
||||||
### 3.4. Is it true that there's an allegory written to describe Humming Consensus?
|
|
||||||
|
|
||||||
Yes. In homage to Leslie Lamport's original paper about the Paxos
|
|
||||||
protocol, "The Part-time Parliamant", there is an allegorical story
|
|
||||||
that describes humming consensus as method to coordinate
|
|
||||||
many composers to write a single piece of music.
|
|
||||||
The full story, full of wonder and mystery, is called
|
|
||||||
["On “Humming Consensus”, an allegory"](http://www.snookles.com/slf-blog/2015/03/01/on-humming-consensus-an-allegory/).
|
|
||||||
There is also a
|
|
||||||
[short followup blog posting](http://www.snookles.com/slf-blog/2015/03/20/on-humming-consensus-an-allegory-part-2/).
|
|
||||||
|
|
||||||
<a name="n3.5">
|
|
||||||
### 3.5. How is Machi tested?
|
|
||||||
|
|
||||||
While not formally proven yet, Machi's implementation of Chain
|
|
||||||
Replication and of humming consensus have been extensively tested with
|
|
||||||
several techniques:
|
|
||||||
|
|
||||||
* We use an executable model based on the QuickCheck framework for
|
|
||||||
property based testing.
|
|
||||||
* In addition to QuickCheck alone, we use the PULSE extension to
|
|
||||||
QuickCheck is used to test the implementation
|
|
||||||
under extremely skewed & unfair scheduling/timing conditions.
|
|
||||||
|
|
||||||
The model includes simulation of asymmetric network partitions. For
|
|
||||||
example, actor A can send messages to actor B, but B cannot send
|
|
||||||
messages to A. If such a partition happens somewhere in a traditional
|
|
||||||
network stack (e.g. a faulty Ethernet cable), any TCP connection
|
|
||||||
between A & B will quickly interrupt communication in _both_
|
|
||||||
directions. In the Machi network partition simulator, network
|
|
||||||
partitions can be truly one-way only.
|
|
||||||
|
|
||||||
After randomly generating a series of network partitions (which may
|
|
||||||
change several times during any single test case) and a random series
|
|
||||||
of cluster operations, an event trace of all cluster activity is used
|
|
||||||
to verify that no safety-critical rules have been violated.
|
|
||||||
|
|
||||||
All test code is available in the [./test](./test) subdirectory.
|
|
||||||
Modules that use QuickCheck will use a file suffix of `_eqc`, for
|
|
||||||
example, [./test/machi_ap_repair_eqc.erl](./test/machi_ap_repair_eqc.erl).
|
|
||||||
|
|
||||||
<a name="n3.6">
|
|
||||||
### 3.6. Does Machi require shared disk storage? e.g. iSCSI, NBD (Network Block Device), Fibre Channel disks
|
|
||||||
|
|
||||||
No, Machi's design assumes that each Machi server is a fully
|
|
||||||
independent hardware and assumes only standard local disks (Winchester
|
|
||||||
and/or SSD style) with local-only interfaces (e.g. SATA, SCSI, PCI) in
|
|
||||||
each machine.
|
|
||||||
|
|
||||||
<a name="n3.7">
|
|
||||||
### 3.7. Does Machi require or assume that servers with large numbers of disks must use RAID-0/1/5/6/10/50/60 to create a single block device?
|
|
||||||
|
|
||||||
No. When used with servers with multiple disks, the intent is to
|
|
||||||
deploy multiple Machi servers per machine: one Machi server per disk.
|
|
||||||
|
|
||||||
* Pro: disk bandwidth and disk storage capacity can be managed at the
|
|
||||||
level of an individual disk.
|
|
||||||
* Pro: failure of an individual disk does not risk data loss on other
|
|
||||||
disks.
|
|
||||||
* Con (or pro, depending on the circumstances): in this configuration,
|
|
||||||
Machi would require additional network bandwidth to repair data on a lost
|
|
||||||
drive instead of intra-machine disk & bus & memory bandwidth that
|
|
||||||
would be required for RAID volume repair
|
|
||||||
* Con: replica placement policy, such as "rack awareness", becomes a
|
|
||||||
larger problem that must be automated. For example, a problem of
|
|
||||||
placement relative to 12 servers is smaller than a placement problem
|
|
||||||
of managing 264 seprate disks (if each of 12 servers has 22 disks).
|
|
||||||
|
|
||||||
<a name="n3.8">
|
|
||||||
### 3.8. What language(s) is Machi written in?
|
|
||||||
|
|
||||||
So far, Machi is written in Erlang, mostly. Machi uses at least one
|
|
||||||
library, [ELevelDB](https://github.com/basho/eleveldb), that is
|
|
||||||
implemented both in C++ and in Erlang, using Erlang NIFs (Native
|
|
||||||
Interface Functions) to allow Erlang code to call C++ functions.
|
|
||||||
|
|
||||||
In the event that we encounter a performance problem that cannot be
|
|
||||||
solved within the Erlang/OTP runtime environment, all of Machi's
|
|
||||||
performance-critical components are small enough to be re-implemented
|
|
||||||
in C, Java, or other "gotta go fast fast FAST!!" programming
|
|
||||||
language. We expect that the Chain Replication manager and other
|
|
||||||
critical "control plane" software will remain in Erlang.
|
|
||||||
|
|
||||||
<a name="n3.9">
|
|
||||||
### 3.9. Can Machi run on Windows? Can Machi run on 32-bit platforms?
|
|
||||||
|
|
||||||
The ELevelDB NIF does not compile or run correctly on Erlang/OTP
|
|
||||||
Windows platforms, nor does it compile correctly on 32-bit platforms.
|
|
||||||
Machi should support all 64-bit UNIX-like platforms that are supported
|
|
||||||
by Erlang/OTP and ELevelDB.
|
|
||||||
|
|
||||||
<a name="n3.10">
|
|
||||||
### 3.10. Does Machi use the Erlang/OTP network distribution system (aka "disterl")?
|
|
||||||
|
|
||||||
No, Machi doesn't use Erlang/OTP's built-in distributed message
|
|
||||||
passing system. The code would be *much* simpler if we did use
|
|
||||||
"disterl". However, due to (premature?) worries about performance, we
|
|
||||||
wanted to have the option of re-writing some Machi components in C or
|
|
||||||
Java or Go or OCaml or COBOL or in-kernel assembly hexadecimal
|
|
||||||
bit-twiddling magicSPEED ... without also having to find a replacement
|
|
||||||
for disterl. (Or without having to re-invent disterl's features in
|
|
||||||
another language.)
|
|
||||||
|
|
||||||
All wire protocols used by Machi are defined & implemented using
|
|
||||||
[Protocol Buffers](https://developers.google.com/protocol-buffers/docs/overview).
|
|
||||||
The definition file can be found at [./src/machi.proto](./src/machi.proto).
|
|
||||||
|
|
||||||
<a name="n3.11">
|
|
||||||
### 3.11. Can I use HTTP to write/read stuff into/from Machi?
|
|
||||||
|
|
||||||
Short answer: No, not yet.
|
|
||||||
|
|
||||||
Longer answer: No, but it was possible as a hack, many months ago, see
|
|
||||||
[primitive/hack'y HTTP interface that is described in this source code commit log](https://github.com/basho/machi/commit/6cebf397232cba8e63c5c9a0a8c02ba391b20fef).
|
|
||||||
Please note that commit `6cebf397232cba8e63c5c9a0a8c02ba391b20fef` is
|
|
||||||
required to try using this feature: the code has since bit-rotted and
|
|
||||||
will not work on today's `master` branch.
|
|
||||||
|
|
||||||
In the long term, we'll probably want the option of an HTTP interface
|
|
||||||
that is as well designed and REST'ful as possible. It's on the
|
|
||||||
internal Basho roadmap. If you'd like to work on a real, not-kludgy
|
|
||||||
HTTP interface to Machi,
|
|
||||||
[please contact us!](https://github.com/basho/machi/blob/master/CONTRIBUTING.md)
|
|
||||||
|
|
297
INSTALLATION.md
297
INSTALLATION.md
|
@ -1,297 +0,0 @@
|
||||||
|
|
||||||
# Installation instructions for Machi
|
|
||||||
|
|
||||||
Machi is still a young enough project that there is no "installation".
|
|
||||||
All development is still done using the Erlang/OTP interactive shell
|
|
||||||
for experimentation, using `make` to compile, and the shell's
|
|
||||||
`l(ModuleName).` command to reload any recompiled modules.
|
|
||||||
|
|
||||||
In the coming months (mid-2015), there are plans to create OS packages
|
|
||||||
for common operating systems and OS distributions, such as FreeBSD and
|
|
||||||
Linux. If building RPM, DEB, PKG, or other OS package managers is
|
|
||||||
your specialty, we could use your help to speed up the process! <b>:-)</b>
|
|
||||||
|
|
||||||
## Development toolchain dependencies
|
|
||||||
|
|
||||||
Machi's dependencies on the developer's toolchain are quite small.
|
|
||||||
|
|
||||||
* Erlang/OTP version 17.0 or later, 32-bit or 64-bit
|
|
||||||
* The `make` utility.
|
|
||||||
* The GNU version of make is not required.
|
|
||||||
* Machi is bundled with a `rebar` package and should be usable on
|
|
||||||
any Erlang/OTP 17.x platform.
|
|
||||||
|
|
||||||
Machi does not use any Erlang NIF or port drivers.
|
|
||||||
|
|
||||||
## Development OS
|
|
||||||
|
|
||||||
At this time, Machi is 100% Erlang. Although we have not tested it,
|
|
||||||
there should be no good reason why Machi cannot run on Erlang/OTP on
|
|
||||||
Windows platforms. Machi has been developed on OS X and FreeBSD and
|
|
||||||
is expected to work on any UNIX-ish platform supported by Erlang/OTP.
|
|
||||||
|
|
||||||
## Compiling the Machi source
|
|
||||||
|
|
||||||
First, clone the Machi source code, then compile it. You will
|
|
||||||
need Erlang/OTP version 17.x to compile.
|
|
||||||
|
|
||||||
cd /some/nice/dev/place
|
|
||||||
git clone https://github.com/basho/machi.git
|
|
||||||
cd machi
|
|
||||||
make
|
|
||||||
make test
|
|
||||||
|
|
||||||
The unit test suite is based on the EUnit framework (bundled with
|
|
||||||
Erlang/OTP 17). The `make test` suite runs on my MacBook in 10
|
|
||||||
seconds or less.
|
|
||||||
|
|
||||||
## Setting up a Machi cluster
|
|
||||||
|
|
||||||
As noted above, everything is done manually at the moment. Here is a
|
|
||||||
rough sketch of day-to-day development workflow.
|
|
||||||
|
|
||||||
### 1. Run the server
|
|
||||||
|
|
||||||
cd /some/nice/dev/place/machi
|
|
||||||
make
|
|
||||||
erl -pz ebin deps/*/ebin +A 253 +K true
|
|
||||||
|
|
||||||
This will start an Erlang shell, plus a few extras.
|
|
||||||
|
|
||||||
* Tell the OTP code loader where to find dependent BEAM files.
|
|
||||||
* Set a large pool (253) of file I/O worker threads
|
|
||||||
* Use a more efficient kernel polling mechanism for network sockets.
|
|
||||||
* If your Erlang/OTP package does not support `+K true`, do not
|
|
||||||
worry. It is an optional flag.
|
|
||||||
|
|
||||||
The following commands will start three Machi FLU server processes and
|
|
||||||
then tell them to form a single chain. Internally, each FLU will have
|
|
||||||
Erlang registered processes with the names `a`, `b`, and `c`, and
|
|
||||||
listen on TCP ports 4444, 4445, and 4446, respectively. Each will use
|
|
||||||
a data directory located in the current directory, e.g. `./data.a`.
|
|
||||||
|
|
||||||
Cut-and-paste the following commands into the CLI at the prompt:
|
|
||||||
|
|
||||||
application:ensure_all_started(machi).
|
|
||||||
machi_flu_psup:start_flu_package(a, 4444, "./data.a", []).
|
|
||||||
machi_flu_psup:start_flu_package(b, 4445, "./data.b", []).
|
|
||||||
D = orddict:from_list([{a,{p_srvr,a,machi_flu1_client,"localhost",4444,[]}},{b,{p_srvr,b,machi_flu1_client,"localhost",4445,[]}}]).
|
|
||||||
machi_chain_manager1:set_chain_members(a_chmgr, D).
|
|
||||||
machi_chain_manager1:set_chain_members(b_chmgr, D).
|
|
||||||
|
|
||||||
If you change the TCP ports of any of the processes, you must make the
|
|
||||||
same change both in the `machi_flu_psup:start_flu_package()` arguments
|
|
||||||
and also in the `D` dictionary.
|
|
||||||
|
|
||||||
The Erlang processes that will be started are arranged in the
|
|
||||||
following hierarchy. See the
|
|
||||||
[machi_flu_psup.erl](http://basho.github.io/machi/edoc/machi_flu_psup.html)
|
|
||||||
EDoc documentation for a description of each of these processes.
|
|
||||||
|
|
||||||
![](https://basho.github.io/machi/images/supervisor-2flus.png)
|
|
||||||
|
|
||||||
### 2. Check the status of the server processes.
|
|
||||||
|
|
||||||
Each Machi FLU is an independent file server. All replication between
|
|
||||||
Machi servers is currently implemented by code on the *client* side.
|
|
||||||
(This will change a bit later in 2015.)
|
|
||||||
|
|
||||||
Use the `read_latest_projection` command on the server CLI, e.g.:
|
|
||||||
|
|
||||||
rr("include/machi_projection.hrl").
|
|
||||||
machi_projection_store:read_latest_projection(a_pstore, private).
|
|
||||||
|
|
||||||
... to query the projection store of the local FLU named `a`.
|
|
||||||
|
|
||||||
If you haven't looked at the server-side description of the various
|
|
||||||
Machi server-side processes, please take a couple minutes to read
|
|
||||||
[machi_flu_psup.erl](http://basho.github.io/machi/edoc/machi_flu_psup.html).
|
|
||||||
|
|
||||||
### 3. Use the machi_cr_client.erl client
|
|
||||||
|
|
||||||
For development work, I run the client & server on the same Erlang
|
|
||||||
VM. It's just easier that way ... but the Machi client & server use
|
|
||||||
TCP to communicate with each other.
|
|
||||||
|
|
||||||
If you are using a separate machine for the client, then compile the
|
|
||||||
Machi source on the client machine. Then run:
|
|
||||||
|
|
||||||
cd /some/nice/dev/place/machi
|
|
||||||
make
|
|
||||||
erl -pz ebin deps/*/ebin
|
|
||||||
|
|
||||||
(You can add `+K true` if you wish ... but for light development work,
|
|
||||||
it doesn't make a big difference.)
|
|
||||||
|
|
||||||
At the CLI, define the dictionary that describes the host & TCP port
|
|
||||||
location for each of the Machi servers. (If you changed the host
|
|
||||||
and/or TCP port values when starting the servers, then place make the
|
|
||||||
same changes here.
|
|
||||||
|
|
||||||
D = orddict:from_list([{a,{p_srvr,a,machi_flu1_client,"localhost",4444,[]}},{b,{p_srvr,b,machi_flu1_client,"localhost",4445,[]}}]).
|
|
||||||
|
|
||||||
Then start a `machi_cr_client` client process.
|
|
||||||
|
|
||||||
{ok, C1} = machi_cr_client:start_link([P || {_,P} <- orddict:to_list(D)]).
|
|
||||||
|
|
||||||
Please keep in mind that this process is **linked** to your CLI
|
|
||||||
process. If you run a CLI command the throws an exception/exits, then
|
|
||||||
this `C1` process will also die! You can start a new one, using a
|
|
||||||
different name, e.g. `C2`. Or you can start a new one by first
|
|
||||||
"forgetting" the CLI's binding for `C1`.
|
|
||||||
|
|
||||||
f(C1).
|
|
||||||
{ok, C1} = machi_cr_client:start_link([P || {_,P} <- orddict:to_list(D)]).
|
|
||||||
|
|
||||||
Now, append a small chunk of data to a file with the prefix
|
|
||||||
`<<"pre">>`.
|
|
||||||
|
|
||||||
12> {ok, C1} = machi_cr_client:start_link([P || {_,P} <- orddict:to_list(D)]).
|
|
||||||
{ok,<0.112.0>}
|
|
||||||
|
|
||||||
13> machi_cr_client:append_chunk(C1, <<"pre">>, <<"Hello, world">>).
|
|
||||||
{ok,{1024,12,<<"pre.G6C116EA.3">>}}
|
|
||||||
|
|
||||||
|
|
||||||
This chunk was written successfully to a file called
|
|
||||||
`<<"pre.5BBL16EA.1">>` at byte offset 1024. Let's fetch it now. And
|
|
||||||
let's see what happens in a couple of error conditions: fetching
|
|
||||||
bytes that "straddle" the end of file, bytes that are after the known
|
|
||||||
end of file, and bytes from a file that has never been written.
|
|
||||||
|
|
||||||
26> machi_cr_client:read_chunk(C1, <<"pre.G6C116EA.3">>, 1024, 12).
|
|
||||||
{ok,<<"Hello, world">>}
|
|
||||||
|
|
||||||
27> machi_cr_client:read_chunk(C1, <<"pre.G6C116EA.3">>, 1024, 777).
|
|
||||||
{error,partial_read}
|
|
||||||
|
|
||||||
28> machi_cr_client:read_chunk(C1, <<"pre.G6C116EA.3">>, 889323, 12).
|
|
||||||
{error,not_written}
|
|
||||||
|
|
||||||
29> machi_cr_client:read_chunk(C1, <<"no-such-file">>, 1024, 12).
|
|
||||||
{error,not_written}
|
|
||||||
|
|
||||||
### 4. Use the `machi_proxy_flu1_client.erl` client
|
|
||||||
|
|
||||||
The `machi_proxy_flu1_client` module implements a simpler client that
|
|
||||||
only uses a single Machi FLU file server. This client is **not**
|
|
||||||
aware of chain replication in any way.
|
|
||||||
|
|
||||||
Let's use this client to verify that the `<<"Hello, world!">> data
|
|
||||||
that we wrote in step #3 was truly written to both FLU servers by the
|
|
||||||
`machi_cr_client` library. We start proxy processes for each of the
|
|
||||||
FLUs, then we'll query each ... but first we also need to ask (at
|
|
||||||
least one of) the servers for the current Machi cluster's Epoch ID.
|
|
||||||
|
|
||||||
{ok, Pa} = machi_proxy_flu1_client:start_link(orddict:fetch(a, D)).
|
|
||||||
{ok, Pb} = machi_proxy_flu1_client:start_link(orddict:fetch(b, D)).
|
|
||||||
{ok, EpochID0} = machi_proxy_flu1_client:get_epoch_id(Pa).
|
|
||||||
machi_proxy_flu1_client:read_chunk(Pa, EpochID0, <<"pre.G6C116EA.3">>, 1024, 12).
|
|
||||||
machi_proxy_flu1_client:read_chunk(Pb, EpochID0, <<"pre.G6C116EA.3">>, 1024, 12).
|
|
||||||
|
|
||||||
### 5. Checking how Chain Replication "read repair" works
|
|
||||||
|
|
||||||
Now, let's cause some trouble: we will write some data only to the
|
|
||||||
head of the chain. By default, all read operations go to the tail of
|
|
||||||
the chain. But, if a value is not written at the tail, then "read
|
|
||||||
repair" ought to verify:
|
|
||||||
|
|
||||||
* Perhaps the value truly is not written at any server in the chain.
|
|
||||||
* Perhaps the value was partially written, i.e. by a buggy or
|
|
||||||
crashed-in-the-middle-of-the-writing-procedure client.
|
|
||||||
|
|
||||||
So, first, let's double-check that the chain is in the order that we
|
|
||||||
expect it to be.
|
|
||||||
|
|
||||||
rr("include/machi_projection.hrl"). % In case you didn't do this earlier.
|
|
||||||
machi_proxy_flu1_client:read_latest_projection(Pa, private).
|
|
||||||
|
|
||||||
The part of the `#projection_v1` record that we're interested in is
|
|
||||||
the `upi`. This is the list of servers that preserve the Update
|
|
||||||
Propagation Invariant property of the Chain Replication algorithm.
|
|
||||||
The output should look something like:
|
|
||||||
|
|
||||||
{ok,#projection_v1{
|
|
||||||
epoch_number = 1119,
|
|
||||||
[...]
|
|
||||||
author_server = b,
|
|
||||||
all_members = [a,b],
|
|
||||||
creation_time = {1432,189599,85392},
|
|
||||||
mode = ap_mode,
|
|
||||||
upi = [a,b],
|
|
||||||
repairing = [],down = [],
|
|
||||||
[...]
|
|
||||||
}
|
|
||||||
|
|
||||||
So, we see `upi=[a,b]`, which means that FLU `a` is the head of the
|
|
||||||
chain and that `b` is the tail.
|
|
||||||
|
|
||||||
Let's append to `a` using the `machi_proxy_flu1_client` to the head
|
|
||||||
and then read from both the head and tail. (If your chain order is
|
|
||||||
different, then please exchange `Pa` and `Pb` in all of the commands
|
|
||||||
below.)
|
|
||||||
|
|
||||||
16> {ok, {Off1,Size1,File1}} = machi_proxy_flu1_client:append_chunk(Pa, EpochID0, <<"foo">>, <<"Hi, again">>).
|
|
||||||
{ok,{1024,9,<<"foo.K63D16M4.1">>}}
|
|
||||||
|
|
||||||
17> machi_proxy_flu1_client:read_chunk(Pa, EpochID0, File1, Off1, Size1). {ok,<<"Hi, again">>}
|
|
||||||
|
|
||||||
18> machi_proxy_flu1_client:read_chunk(Pb, EpochID0, File1, Off1, Size1).
|
|
||||||
{error,not_written}
|
|
||||||
|
|
||||||
That is correct! Now, let's read the same file & offset using the
|
|
||||||
client that understands chain replication. Then we will try reading
|
|
||||||
directly from FLU `b` again ... we should see something different.
|
|
||||||
|
|
||||||
19> {ok, C2} = machi_cr_client:start_link([P || {_,P} <- orddict:to_list(D)]).
|
|
||||||
{ok,<0.113.0>}
|
|
||||||
|
|
||||||
20> machi_cr_client:read_chunk(C2, File1, Off1, Size1).
|
|
||||||
{ok,<<"Hi, again">>}
|
|
||||||
|
|
||||||
21> machi_proxy_flu1_client:read_chunk(Pb, EpochID0, File1, Off1, Size1).
|
|
||||||
{ok,<<"Hi, again">>}
|
|
||||||
|
|
||||||
That is correct! The command at prompt #20 automatically performed
|
|
||||||
"read repair" on FLU `b`.
|
|
||||||
|
|
||||||
### 6. Exploring what happens when a server is stopped, data written, and server restarted
|
|
||||||
|
|
||||||
Cut-and-paste the following into your CLI. We assume that your CLI
|
|
||||||
still remembers the value of the `D` dictionary from the previous
|
|
||||||
steps above. We will stop FLU `a`, write one thousand small
|
|
||||||
chunks, then restart FLU `a`, then see what happens.
|
|
||||||
|
|
||||||
{ok, C3} = machi_cr_client:start_link([P || {_,P} <- orddict:to_list(D)]).
|
|
||||||
machi_flu_psup:stop_flu_package(a).
|
|
||||||
[machi_cr_client:append_chunk(C3, <<"foo">>, <<"Lots of stuff">>) || _ <- lists:seq(1,1000)].
|
|
||||||
machi_flu_psup:start_flu_package(a, 4444, "./data.a", []).
|
|
||||||
|
|
||||||
About 10 seconds after we restarting `a` with the
|
|
||||||
`machi_flu_psup:start_flu_package()` function, this appears on the
|
|
||||||
console:
|
|
||||||
|
|
||||||
=INFO REPORT==== 21-May-2015::15:53:46 ===
|
|
||||||
Repair start: tail b of [b] -> [a], ap_mode ID {b,{1432,191226,707262}}
|
|
||||||
MissingFileSummary [{<<"foo.CYLJ16ZT.1">>,{14024,[a]}}]
|
|
||||||
Make repair directives: . done
|
|
||||||
Out-of-sync data for FLU a: 0.1 MBytes
|
|
||||||
Out-of-sync data for FLU b: 0.0 MBytes
|
|
||||||
Execute repair directives: .......... done
|
|
||||||
|
|
||||||
=INFO REPORT==== 21-May-2015::15:53:47 ===
|
|
||||||
Repair success: tail b of [b] finished ap_mode repair ID {b,{1432,191226,707262}}: ok
|
|
||||||
Stats [{t_in_files,0},{t_in_chunks,1000},{t_in_bytes,13000},{t_out_files,0},{t_out_chunks,1000},{t_out_bytes,13000},{t_bad_chunks,0},{t_elapsed_seconds,0.647}]
|
|
||||||
|
|
||||||
The data repair process, executed by `b`'s chain manager, found 1000
|
|
||||||
chunks that were out of sync and copied them to `a` successfully.
|
|
||||||
|
|
||||||
### 7. Exploring the rest of the client APIs
|
|
||||||
|
|
||||||
Please see the EDoc documentation for the client APIs. Feel free to
|
|
||||||
explore!
|
|
||||||
|
|
||||||
* [Erlang type definitions for the client APIs](http://basho.github.io/machi/edoc/machi_flu1_client.html)
|
|
||||||
* [EDoc for machi_cr_client.erl](http://basho.github.io/machi/edoc/machi_cr_client.html)
|
|
||||||
* [EDoc for machi_proxy_flu1_client.erl](http://basho.github.io/machi/edoc/machi_proxy_flu1_client.html)
|
|
||||||
* [Top level EDoc collection](http://basho.github.io/machi/edoc/)
|
|
178
LICENSE
178
LICENSE
|
@ -1,178 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
94
Makefile
94
Makefile
|
@ -1,94 +0,0 @@
|
||||||
REPO ?= machi
|
|
||||||
PKG_REVISION ?= $(shell git describe --tags)
|
|
||||||
PKG_BUILD = 1
|
|
||||||
BASE_DIR = $(shell pwd)
|
|
||||||
ERLANG_BIN = $(shell dirname $(shell which erl))
|
|
||||||
REBAR := $(shell which rebar)
|
|
||||||
ifeq ($(REBAR),)
|
|
||||||
REBAR = $(BASE_DIR)/rebar
|
|
||||||
endif
|
|
||||||
OVERLAY_VARS ?=
|
|
||||||
EUNIT_OPTS = -v
|
|
||||||
|
|
||||||
.PHONY: rel stagedevrel deps package pkgclean edoc
|
|
||||||
|
|
||||||
all: deps compile
|
|
||||||
|
|
||||||
compile:
|
|
||||||
$(REBAR) compile
|
|
||||||
|
|
||||||
## Make reltool happy by creating a fake entry in the deps dir for
|
|
||||||
## machi, because reltool really wants to have a path with
|
|
||||||
## "machi/ebin" at the end, but we also don't want infinite recursion
|
|
||||||
## if we just symlink "deps/machi" -> ".."
|
|
||||||
|
|
||||||
generate:
|
|
||||||
rm -rf deps/machi
|
|
||||||
mkdir deps/machi
|
|
||||||
ln -s ../../ebin deps/machi
|
|
||||||
ln -s ../../src deps/machi
|
|
||||||
$(REBAR) generate $(OVERLAY_VARS) 2>&1 | grep -v 'command does not apply to directory'
|
|
||||||
|
|
||||||
deps:
|
|
||||||
$(REBAR) get-deps
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(REBAR) -r clean
|
|
||||||
|
|
||||||
edoc: edoc-clean
|
|
||||||
$(REBAR) skip_deps=true doc
|
|
||||||
|
|
||||||
edoc-clean:
|
|
||||||
rm -f edoc/*.png edoc/*.html edoc/*.css edoc/edoc-info
|
|
||||||
|
|
||||||
pulse: compile
|
|
||||||
@echo Sorry, PULSE test needs maintenance. -SLF
|
|
||||||
#env USE_PULSE=1 $(REBAR) skip_deps=true clean compile
|
|
||||||
#env USE_PULSE=1 $(REBAR) skip_deps=true -D PULSE eunit -v
|
|
||||||
|
|
||||||
##
|
|
||||||
## Release targets
|
|
||||||
##
|
|
||||||
rel: deps compile generate
|
|
||||||
|
|
||||||
relclean:
|
|
||||||
rm -rf rel/$(REPO)
|
|
||||||
|
|
||||||
stage : rel
|
|
||||||
$(foreach dep,$(wildcard deps/*), rm -rf rel/$(REPO)/lib/$(shell basename $(dep))* && ln -sf $(abspath $(dep)) rel/$(REPO)/lib;)
|
|
||||||
|
|
||||||
##
|
|
||||||
## Developer targets
|
|
||||||
##
|
|
||||||
## devN - Make a dev build for node N
|
|
||||||
## stagedevN - Make a stage dev build for node N (symlink libraries)
|
|
||||||
## devrel - Make a dev build for 1..$DEVNODES
|
|
||||||
## stagedevrel Make a stagedev build for 1..$DEVNODES
|
|
||||||
##
|
|
||||||
## Example, make a 68 node devrel cluster
|
|
||||||
## make stagedevrel DEVNODES=68
|
|
||||||
|
|
||||||
.PHONY : stagedevrel devrel
|
|
||||||
DEVNODES ?= 3
|
|
||||||
|
|
||||||
# 'seq' is not available on all *BSD, so using an alternate in awk
|
|
||||||
SEQ = $(shell awk 'BEGIN { for (i = 1; i < '$(DEVNODES)'; i++) printf("%i ", i); print i ;exit(0);}')
|
|
||||||
|
|
||||||
$(eval stagedevrel : $(foreach n,$(SEQ),stagedev$(n)))
|
|
||||||
$(eval devrel : $(foreach n,$(SEQ),dev$(n)))
|
|
||||||
|
|
||||||
dev% : all
|
|
||||||
mkdir -p dev
|
|
||||||
rel/gen_dev $@ rel/vars/dev_vars.config.src rel/vars/$@_vars.config
|
|
||||||
(cd rel && ../rebar generate target_dir=../dev/$@ overlay_vars=vars/$@_vars.config)
|
|
||||||
|
|
||||||
stagedev% : dev%
|
|
||||||
$(foreach dep,$(wildcard deps/*), rm -rf dev/$^/lib/$(shell basename $(dep))* && ln -sf $(abspath $(dep)) dev/$^/lib;)
|
|
||||||
|
|
||||||
devclean: clean
|
|
||||||
rm -rf dev
|
|
||||||
|
|
||||||
DIALYZER_APPS = kernel stdlib sasl erts ssl compiler eunit crypto public_key syntax_tools
|
|
||||||
PLT = $(HOME)/.machi_dialyzer_plt
|
|
||||||
|
|
||||||
include tools.mk
|
|
6
NOTICE
6
NOTICE
|
@ -1,6 +0,0 @@
|
||||||
Machi
|
|
||||||
Copyright 2007-2015 Basho Technologies
|
|
||||||
|
|
||||||
This product contains code developed at Basho Technologies.
|
|
||||||
(http://www.basho.com/)
|
|
||||||
|
|
174
README.md
174
README.md
|
@ -1,174 +0,0 @@
|
||||||
# Machi: a distributed, decentralized blob/large file store
|
|
||||||
|
|
||||||
[Travis-CI](http://travis-ci.org/basho/machi) :: ![Travis-CI](https://secure.travis-ci.org/basho/machi.png)
|
|
||||||
|
|
||||||
Outline
|
|
||||||
|
|
||||||
1. [Why another blob/file store?](#sec1)
|
|
||||||
2. [Where to learn more about Machi](#sec2)
|
|
||||||
3. [Development status summary](#sec3)
|
|
||||||
4. [Contributing to Machi's development](#sec4)
|
|
||||||
|
|
||||||
<a name="sec1">
|
|
||||||
## 1. Why another blob/file store?
|
|
||||||
|
|
||||||
Our goal is a robust & reliable, distributed, highly available, large
|
|
||||||
file and blob store. Such stores already exist, both in the open source world
|
|
||||||
and in the commercial world. Why reinvent the wheel? We believe
|
|
||||||
there are three reasons, ordered by decreasing rarity.
|
|
||||||
|
|
||||||
1. We want end-to-end checksums for all file data, from the initial
|
|
||||||
file writer to every file reader, anywhere, all the time.
|
|
||||||
2. We need flexibility to trade consistency for availability:
|
|
||||||
e.g. weak consistency in exchange for being available in cases
|
|
||||||
of partial system failure.
|
|
||||||
3. We want to manage file replicas in a way that's provably correct
|
|
||||||
and also easy to test.
|
|
||||||
|
|
||||||
Criteria #3 is difficult to find in the open source world but perhaps
|
|
||||||
not impossible.
|
|
||||||
|
|
||||||
If we have app use cases where availability is more important than
|
|
||||||
consistency, then systems that meet criteria #2 are also rare.
|
|
||||||
Most file stores provide only strong consistency and therefore
|
|
||||||
have unavoidable, unavailable behavior when parts of the system
|
|
||||||
fail.
|
|
||||||
What if we want a file store that is always available to write new
|
|
||||||
file data and attempts best-effort file reads?
|
|
||||||
|
|
||||||
If we really do care about data loss and/or data corruption, then we
|
|
||||||
really want both #3 and #1. Unfortunately, systems that meet
|
|
||||||
criteria #1 are _very rare_. (Nonexistant?)
|
|
||||||
Why? This is 2015. We have decades of research that shows
|
|
||||||
that computer hardware can (and
|
|
||||||
indeed does) corrupt data at nearly every level of the modern
|
|
||||||
client/server application stack. Systems with end-to-end data
|
|
||||||
corruption detection should be ubiquitous today. Alas, they are not.
|
|
||||||
|
|
||||||
Machi is an effort to change the deplorable state of the world, one
|
|
||||||
Erlang function at a time.
|
|
||||||
|
|
||||||
<a name="sec2">
|
|
||||||
## 2. Where to learn more about Machi
|
|
||||||
|
|
||||||
The two major design documents for Machi are now mostly stable.
|
|
||||||
Please see the [doc](./doc) directory's [README](./doc) for details.
|
|
||||||
|
|
||||||
We also have a
|
|
||||||
[Frequently Asked Questions (FAQ) list](./FAQ.md).
|
|
||||||
|
|
||||||
Scott recently (November 2015) gave a presentation at the
|
|
||||||
[RICON 2015 conference](http://ricon.io) about one of the techniques
|
|
||||||
used by Machi; "Managing Chain Replication Metadata with
|
|
||||||
Humming Consensus" is available online now.
|
|
||||||
* [slides (PDF format)](http://ricon.io/speakers/slides/Scott_Fritchie_Ricon_2015.pdf)
|
|
||||||
* [video](https://www.youtube.com/watch?v=yR5kHL1bu1Q)
|
|
||||||
|
|
||||||
See later in this document for how to run the Humming Consensus demos,
|
|
||||||
including the network partition simulator.
|
|
||||||
|
|
||||||
<a name="sec3">
|
|
||||||
## 3. Development status summary
|
|
||||||
|
|
||||||
Mid-March 2016: The Machi development team has been downsized in
|
|
||||||
recent months, and the pace of development has slowed. Here is a
|
|
||||||
summary of the status of Machi's major components.
|
|
||||||
|
|
||||||
* Humming Consensus and the chain manager
|
|
||||||
* No new safety bugs have been found by model-checking tests.
|
|
||||||
* A new document,
|
|
||||||
[Hands-on experiments with Machi and Humming Consensus](doc/humming-consensus-demo.md)
|
|
||||||
is now available. It is a tutorial for setting up a 3 virtual
|
|
||||||
machine Machi cluster and how to demonstrate the chain manager's
|
|
||||||
reactions to server stops & starts, crashes & restarts, and pauses
|
|
||||||
(simulated by `SIGSTOP` and `SIGCONT`).
|
|
||||||
* The chain manager can still make suboptimal-but-safe choices for
|
|
||||||
chain transitions when a server hangs/pauses temporarily.
|
|
||||||
* Recent chain manager changes have made the instability window
|
|
||||||
much shorter when the slow/paused server resumes execution.
|
|
||||||
* Scott believes that a modest change to the chain manager's
|
|
||||||
calculation of a new projection can reduce flapping in this (and
|
|
||||||
many other cases) less likely. Currently, the new local
|
|
||||||
projection is calculated using only local state (i.e., the chain
|
|
||||||
manager's internal state + the fitness server's state).
|
|
||||||
However, if the "latest" projection read from the public
|
|
||||||
projection stores were also input to the new projection
|
|
||||||
calculation function, then many obviously bad projections can be
|
|
||||||
avoided without needing rounds of Humming Consensus to
|
|
||||||
demonstrate that a bad projection is bad.
|
|
||||||
|
|
||||||
* FLU/data server process
|
|
||||||
* All known correctness bugs have been fixed.
|
|
||||||
* Performance has not yet been measured. Performance measurement
|
|
||||||
and enhancements are scheduled to start in the middle of March 2016.
|
|
||||||
(This will include a much-needed update to the `basho_bench` driver.)
|
|
||||||
|
|
||||||
* Access protocols and client libraries
|
|
||||||
* The protocol used by both external clients and internally (instead
|
|
||||||
of using Erlang's native message passing mechanisms) is based on
|
|
||||||
Protocol Buffers.
|
|
||||||
* (Machi PB protocol specification: ./src/machi.proto)[./src/machi.proto]
|
|
||||||
* At the moment, the PB specification contains two protocols.
|
|
||||||
Sometime in the near future, the spec will be split to separate
|
|
||||||
the external client API (the "high" protocol) from the internal
|
|
||||||
communication API (the "low" protocol).
|
|
||||||
|
|
||||||
* Recent conference talks about Machi
|
|
||||||
* Erlang Factory San Francisco 2016
|
|
||||||
[the slides and video recording](http://www.erlang-factory.com/sfbay2016/scott-lystig-fritchie)
|
|
||||||
will be available a few weeks after the conference ends on March
|
|
||||||
11, 2016.
|
|
||||||
* Ricon 2015
|
|
||||||
* [The slides](http://ricon.io/archive/2015/slides/Scott_Fritchie_Ricon_2015.pdf)
|
|
||||||
* and the [video recording](https://www.youtube.com/watch?v=yR5kHL1bu1Q&index=13&list=PL9Jh2HsAWHxIc7Tt2M6xez_TOP21GBH6M)
|
|
||||||
are now available.
|
|
||||||
* If you would like to run the Humming Consensus code (with or without
|
|
||||||
the network partition simulator) as described in the RICON 2015
|
|
||||||
presentation, please see the
|
|
||||||
[Humming Consensus demo doc](./doc/humming_consensus_demo.md).
|
|
||||||
|
|
||||||
<a name="sec4">
|
|
||||||
## 4. Contributing to Machi's development
|
|
||||||
|
|
||||||
### 4.1 License
|
|
||||||
|
|
||||||
Basho Technologies, Inc. as committed to licensing all work for Machi
|
|
||||||
under the
|
|
||||||
[Apache Public License version 2](./LICENSE). All authors of source code
|
|
||||||
and documentation who agree with these licensing terms are welcome to
|
|
||||||
contribute their ideas in any form: suggested design or features,
|
|
||||||
documentation, and source code.
|
|
||||||
|
|
||||||
Machi is still a very young project within Basho, with a small team of
|
|
||||||
developers; please bear with us as we grow out of "toddler" stage into
|
|
||||||
a more mature open source software project.
|
|
||||||
We invite all contributors to review the
|
|
||||||
[CONTRIBUTING.md](./CONTRIBUTING.md) document for guidelines for
|
|
||||||
working with the Basho development team.
|
|
||||||
|
|
||||||
### 4.2 Development environment requirements
|
|
||||||
|
|
||||||
All development to date has been done with Erlang/OTP version 17 on OS
|
|
||||||
X. The only known limitations for using R16 are minor type
|
|
||||||
specification difference between R16 and 17, but we strongly suggest
|
|
||||||
continuing development using version 17.
|
|
||||||
|
|
||||||
We also assume that you have the standard UNIX/Linux developer
|
|
||||||
tool chain for C and C++ applications. Also, we assume
|
|
||||||
that Git and GNU Make are available.
|
|
||||||
The utility used to compile the Machi source code,
|
|
||||||
`rebar`, is pre-compiled and included in the repo.
|
|
||||||
For more details, please see the
|
|
||||||
[Machi development environment prerequisites doc](./doc/dev-prerequisites.md).
|
|
||||||
|
|
||||||
Machi has a dependency on the
|
|
||||||
[ELevelDB](https://github.com/basho/eleveldb) library. ELevelDB only
|
|
||||||
supports UNIX/Linux OSes and 64-bit versions of Erlang/OTP only; we
|
|
||||||
apologize to Windows-based and 32-bit-based Erlang developers for this
|
|
||||||
restriction.
|
|
||||||
|
|
||||||
### 4.3 New protocols and features
|
|
||||||
|
|
||||||
If you'd like to work on a protocol such as Thrift, UBF,
|
|
||||||
msgpack over UDP, or some other protocol, let us know by
|
|
||||||
[opening an issue to discuss it](./issues/new).
|
|
|
@ -1,114 +0,0 @@
|
||||||
* To Do list
|
|
||||||
|
|
||||||
** DONE remove the escript* stuff from machi_util.erl
|
|
||||||
** DONE Add functions to manipulate 1-chain projections
|
|
||||||
|
|
||||||
- Add epoch ID = epoch number + checksum of projection!
|
|
||||||
Done via compare() func.
|
|
||||||
|
|
||||||
** DONE Change all protocol ops to add epoch ID
|
|
||||||
** DONE Add projection store to each FLU.
|
|
||||||
|
|
||||||
*** DONE What should the API look like? (borrow from chain mgr PoC?)
|
|
||||||
|
|
||||||
Yeah, I think that's pretty complete. Steal it now, worry later.
|
|
||||||
|
|
||||||
*** DONE Choose protocol & TCP port. Share with get/put? Separate?
|
|
||||||
|
|
||||||
Hrm, I like the idea of having a single TCP port to talk to any single
|
|
||||||
FLU.
|
|
||||||
|
|
||||||
To make the protocol "easy" to hack, how about using the same basic
|
|
||||||
method as append/write where there's a variable size blob. But we'll
|
|
||||||
format that blob as a term_to_binary(). Then dispatch to a single
|
|
||||||
func, and pattern match Erlang style in that func.
|
|
||||||
|
|
||||||
*** DONE Do it.
|
|
||||||
|
|
||||||
** DONE Finish OTP'izing the Chain Manager with FLU & proj store processes
|
|
||||||
** DONE Eliminate the timeout exception for the client: just {error,timeout} ret
|
|
||||||
** DONE Move prototype/chain-manager code to "top" of source tree
|
|
||||||
*** DONE Preserve current test code (leave as-is? tiny changes?)
|
|
||||||
*** DONE Make chain manager code flexible enough to run "real world" or "sim"
|
|
||||||
** DONE Add projection wedging logic to each FLU.
|
|
||||||
** DONE Implement real data repair, orchestrated by the chain manager
|
|
||||||
** DONE Change all protocol ops to enforce the epoch ID
|
|
||||||
|
|
||||||
- Add no-wedging state to make testing easier?
|
|
||||||
|
|
||||||
|
|
||||||
** DONE Adapt the projection-aware, CR-implementing client from demo-day
|
|
||||||
** DONE Add major comment sections to the CR-impl client
|
|
||||||
** DONE Simple basho_bench driver, put some unscientific chalk on the benchtop
|
|
||||||
** TODO Create parallel PULSE test for basic API plus chain manager repair
|
|
||||||
** DONE Add client-side vs. server-side checksum type, expand client API?
|
|
||||||
** TODO Add gproc and get rid of registered name rendezvous
|
|
||||||
*** TODO Fixes the atom table leak
|
|
||||||
*** TODO Fixes the problem of having active sequencer for the same prefix
|
|
||||||
on two FLUS in the same VM
|
|
||||||
|
|
||||||
** TODO Fix all known bugs/cruft with Chain Manager (list below)
|
|
||||||
*** DONE Fix known bugs
|
|
||||||
*** DONE Clean up crufty TODO comments and other obvious cruft
|
|
||||||
*** TODO Re-add verification step of stable epochs, including inner projections!
|
|
||||||
*** TODO Attempt to remove cruft items in flapping_i?
|
|
||||||
|
|
||||||
** TODO Move the FLU server to gen_server behavior?
|
|
||||||
|
|
||||||
|
|
||||||
* DONE Chain manager CP mode, Plan B
|
|
||||||
** SKIP Maybe? Change ch_mgr to use middleworker
|
|
||||||
**** DONE Is it worthwhile? Is the parallelism so important? No, probably.
|
|
||||||
**** SKIP Move middleworker func to utility module?
|
|
||||||
** DONE Add new proc to psup group
|
|
||||||
*** DONE Name: machi_fitness
|
|
||||||
** DONE ch_mgr keeps its current proc struct: i.e. same 1 proc as today
|
|
||||||
** NO chmgr asks hosed mgr for hosed list @ start of react_to_env
|
|
||||||
** DONE For all hosed, do *async*: try to read latest proj.
|
|
||||||
*** NO If OK, inform hosed mgr: status change will be used by next HC iter.
|
|
||||||
*** NO If fail, no change, because that server is already known to be hosed
|
|
||||||
*** DONE For all non-hosed, continue as the chain manager code does today
|
|
||||||
*** DONE Any new errors are added to UpNodes/DownNodes tracking as used today
|
|
||||||
*** DONE At end of react loop, if UpNodes list differs, inform hosed mgr.
|
|
||||||
|
|
||||||
* DONE fitness_mon, the fitness monitor
|
|
||||||
** DONE Map key & val sketch
|
|
||||||
|
|
||||||
Logical sketch:
|
|
||||||
|
|
||||||
Map key: ObservingServerName::atom()
|
|
||||||
|
|
||||||
Map val: { ObservingServerLastModTime::now(),
|
|
||||||
UnfitList::list(ServerName::atom()),
|
|
||||||
AdminDownList::list(ServerName::atom()),
|
|
||||||
Props::proplist() }
|
|
||||||
|
|
||||||
Implementation sketch:
|
|
||||||
|
|
||||||
1. Use CRDT map.
|
|
||||||
2. If map key is not atom, then atom->string or atom->binary is fine.
|
|
||||||
3. For map value, is it possible CRDT LWW type?
|
|
||||||
|
|
||||||
** DONE Investigate riak_dt data structure definition, manipulating, etc.
|
|
||||||
** DONE Add dependency on riak_dt
|
|
||||||
** DONE Update is an entire dict from Observer O
|
|
||||||
*** DONE Merge my pending map + update map + my last mod time + my unfit list
|
|
||||||
*** DONE if merged /= pending:
|
|
||||||
**** DONE Schedule async tick (more)
|
|
||||||
|
|
||||||
Tick message contains list of servers with differing state as of this
|
|
||||||
instant in time... we want to avoid triggering decisions about
|
|
||||||
fitness/unfitness for other servers where we might have received less
|
|
||||||
than a full time period's worth of waiting.
|
|
||||||
|
|
||||||
**** DONE Spam merged map to All_list -- [Me]
|
|
||||||
**** DONE Set pending <- merged
|
|
||||||
|
|
||||||
*** DONE When we receive an async tick
|
|
||||||
**** DONE set active map <- pending map for all servers in ticks list
|
|
||||||
**** DONE Send ch_mgr a react_to_env tick trigger
|
|
||||||
*** DONE react_to_env tick trigger actions
|
|
||||||
**** DONE Filter active map to remove stale entries (i.e. no update in 1 hour)
|
|
||||||
**** DONE If time since last map spam is too long, spam our *pending* map
|
|
||||||
**** DONE Proceed with normal react processing, using *active* map for AllHosed!
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
### The auto-generated code of machi_pb.beam has some complaints, not fixed yet.
|
|
||||||
machi_pb.erl:0:
|
|
||||||
##################################################
|
|
||||||
######## Specific types #####################
|
|
||||||
##################################################
|
|
||||||
Unknown types:
|
|
||||||
basho_bench_config:get/2
|
|
||||||
machi_partition_simulator:get/1
|
|
||||||
hamcrest:matchspec/0
|
|
||||||
##################################################
|
|
||||||
######## Specific messages #####################
|
|
||||||
##################################################
|
|
||||||
machi_chain_manager1.erl:2473: The created fun has no local return
|
|
||||||
machi_chain_manager1.erl:2184: The pattern <_P1, P2, Else = {'expected_author2', UPI1_tail, _}> can never match the type <#projection_v1{epoch_number::'undefined' | non_neg_integer(),epoch_csum::'undefined' | binary(),author_server::atom(),chain_name::atom(),all_members::'undefined' | [atom()],witnesses::[atom()],creation_time::'undefined' | {non_neg_integer(),non_neg_integer(),non_neg_integer()},mode::'ap_mode' | 'cp_mode',upi::'undefined' | [atom()],repairing::'undefined' | [atom()],down::'undefined' | [atom()],dbg::'undefined' | [any()],dbg2::'undefined' | [any()],members_dict::'undefined' | [{_,_}]},#projection_v1{epoch_number::'undefined' | non_neg_integer(),epoch_csum::binary(),author_server::atom(),chain_name::atom(),all_members::'undefined' | [atom()],witnesses::[atom()],creation_time::'undefined' | {non_neg_integer(),non_neg_integer(),non_neg_integer()},mode::'ap_mode' | 'cp_mode',upi::'undefined' | [atom()],repairing::'undefined' | [atom()],down::'undefined' | [atom()],dbg::'undefined' | [any()],dbg2::'undefined' | [any()],members_dict::'undefined' | [{_,_}]},'true'>
|
|
||||||
machi_chain_manager1.erl:2233: The pattern <_P1 = {'projection_v1', _, _, _, _, _, _, _, 'cp_mode', UPI1, Repairing1, _, _, _, _}, _P2 = {'projection_v1', _, _, _, _, _, _, _, 'cp_mode', UPI2, Repairing2, _, _, _, _}, Else = {'epoch_not_si', EpochX, 'not_gt', EpochY}> can never match the type <#projection_v1{epoch_number::'undefined' | non_neg_integer(),epoch_csum::'undefined' | binary(),author_server::atom(),chain_name::atom(),all_members::'undefined' | [atom()],witnesses::[atom()],creation_time::'undefined' | {non_neg_integer(),non_neg_integer(),non_neg_integer()},mode::'ap_mode' | 'cp_mode',upi::'undefined' | [atom()],repairing::'undefined' | [atom()],down::'undefined' | [atom()],dbg::'undefined' | [any()],dbg2::'undefined' | [any()],members_dict::'undefined' | [{_,_}]},#projection_v1{epoch_number::'undefined' | non_neg_integer(),epoch_csum::binary(),author_server::atom(),chain_name::atom(),all_members::'undefined' | [atom()],witnesses::[atom()],creation_time::'undefined' | {non_neg_integer(),non_neg_integer(),non_neg_integer()},mode::'ap_mode' | 'cp_mode',upi::'undefined' | [atom()],repairing::'undefined' | [atom()],down::'undefined' | [atom()],dbg::'undefined' | [any()],dbg2::'undefined' | [any()],members_dict::'undefined' | [{_,_}]},'true'>
|
|
|
@ -1,74 +0,0 @@
|
||||||
## Machi Documentation Overview
|
|
||||||
|
|
||||||
For a Web-browsable version of a snapshot of the source doc "EDoc"
|
|
||||||
Erlang documentation, please use this link:
|
|
||||||
[Machi EDoc snapshot](https://basho.github.io/machi/edoc/).
|
|
||||||
|
|
||||||
## Documents in this directory
|
|
||||||
|
|
||||||
### high-level-machi.pdf
|
|
||||||
|
|
||||||
[high-level-machi.pdf](high-level-machi.pdf)
|
|
||||||
is an overview of the high level design for
|
|
||||||
Machi. Its abstract:
|
|
||||||
|
|
||||||
> Our goal is a robust & reliable, distributed, highly available large
|
|
||||||
> file store based upon write-once registers, append-only files, Chain
|
|
||||||
> Replication, and client-server style architecture. All members of
|
|
||||||
> the cluster store all of the files. Distributed load
|
|
||||||
> balancing/sharding of files is outside of the scope of this system.
|
|
||||||
> However, it is a high priority that this system be able to integrate
|
|
||||||
> easily into systems that do provide distributed load balancing,
|
|
||||||
> e.g., Riak Core. Although strong consistency is a major feature of
|
|
||||||
> Chain Replication, this document will focus mainly on eventual
|
|
||||||
> consistency features --- strong consistency design will be discussed
|
|
||||||
> in a separate document.
|
|
||||||
|
|
||||||
### high-level-chain-mgr.pdf
|
|
||||||
|
|
||||||
[high-level-chain-mgr.pdf](high-level-chain-mgr.pdf)
|
|
||||||
is an overview of the techniques used by
|
|
||||||
Machi to manage Chain Replication metadata state. It also provides an
|
|
||||||
introduction to the Humming Consensus algorithm. Its abstract:
|
|
||||||
|
|
||||||
> Machi is an immutable file store, now in active development by Basho
|
|
||||||
> Japan KK. Machi uses Chain Replication to maintain strong consistency
|
|
||||||
> of file updates to all replica servers in a Machi cluster. Chain
|
|
||||||
> Replication is a variation of primary/backup replication where the
|
|
||||||
> order of updates between the primary server and each of the backup
|
|
||||||
> servers is strictly ordered into a single "chain". Management of
|
|
||||||
> Chain Replication's metadata, e.g., "What is the current order of
|
|
||||||
> servers in the chain?", remains an open research problem. The
|
|
||||||
> current state of the art for Chain Replication metadata management
|
|
||||||
> relies on an external oracle (e.g., ZooKeeper) or the Elastic
|
|
||||||
> Replication algorithm.
|
|
||||||
>
|
|
||||||
> This document describes the Machi chain manager, the component
|
|
||||||
> responsible for managing Chain Replication metadata state. The chain
|
|
||||||
> manager uses a new technique, based on a variation of CORFU, called
|
|
||||||
> "humming consensus".
|
|
||||||
> Humming consensus does not require active participation by all or even
|
|
||||||
> a majority of participants to make decisions. Machi's chain manager
|
|
||||||
> bases its logic on humming consensus to make decisions about how to
|
|
||||||
> react to changes in its environment, e.g. server crashes, network
|
|
||||||
> partitions, and changes by Machi cluster admnistrators. Once a
|
|
||||||
> decision is made during a virtual time epoch, humming consensus will
|
|
||||||
> eventually discover if other participants have made a different
|
|
||||||
> decision during that epoch. When a differing decision is discovered,
|
|
||||||
> new time epochs are proposed in which a new consensus is reached and
|
|
||||||
> disseminated to all available participants.
|
|
||||||
|
|
||||||
### chain-self-management-sketch.org
|
|
||||||
|
|
||||||
[chain-self-management-sketch.org](chain-self-management-sketch.org)
|
|
||||||
is a mostly-deprecated draft of
|
|
||||||
an introduction to the
|
|
||||||
self-management algorithm proposed for Machi. Most material has been
|
|
||||||
moved to the [high-level-chain-mgr.pdf](high-level-chain-mgr.pdf) document.
|
|
||||||
|
|
||||||
### cluster (directory)
|
|
||||||
|
|
||||||
This directory contains the sketch of the cluster design
|
|
||||||
strawman for partitioning/distributing/sharding files across a large
|
|
||||||
number of independent Machi chains.
|
|
||||||
|
|
|
@ -1,258 +0,0 @@
|
||||||
|
|
||||||
# Using basho_bench to twiddle with Machi
|
|
||||||
|
|
||||||
"Twiddle"? Really, is that a word? (Yes, it is a real English word.)
|
|
||||||
|
|
||||||
## Benchmarking Machi's performance ... no, don't do it.
|
|
||||||
|
|
||||||
Machi isn't ready for benchmark testing. Its public-facing API isn't
|
|
||||||
finished yet. Its internal APIs aren't quite finished yet either. So
|
|
||||||
any results of "benchmarking" effort is something that has even less
|
|
||||||
value **N** months from now than the usual benchmarking effort.
|
|
||||||
|
|
||||||
However, there are uses for a benchmark tool. For example, one of my
|
|
||||||
favorites is to put **stress** on a system. I don't care about
|
|
||||||
average or 99th-percentile latencies, but I **might** care very much
|
|
||||||
about behavior.
|
|
||||||
|
|
||||||
* What happens if a Machi system is under moderate load, and then I
|
|
||||||
stop one of the servers? What happens?
|
|
||||||
* How quickly do the chain managers react?
|
|
||||||
* How quickly do the client libraries within Machi react?
|
|
||||||
* How quickly do the external client API libraries react?
|
|
||||||
|
|
||||||
* What happens if a Machi system is under heavy load, for example,
|
|
||||||
100% CPU load. Not all 100% might be the Machi services. Some CPU
|
|
||||||
consumption might be from the load generator, like `basho_bench`
|
|
||||||
itself that is running on the same machine as a Machi server. Or
|
|
||||||
perhaps it's a tiny C program that I wrote:
|
|
||||||
|
|
||||||
main()
|
|
||||||
{ while (1) { ; } }
|
|
||||||
|
|
||||||
## An example of how adding moderate stress can find weird bugs
|
|
||||||
|
|
||||||
The driver/plug-in module for `basho_bench` is only a few hours old.
|
|
||||||
(I'm writing on Wednesday, 2015-05-20.) But just now, I configured my
|
|
||||||
basho_bench config file to try to contact a Machi cluster of three
|
|
||||||
nodes ... but really, only one was running. The client library,
|
|
||||||
`machi_cr_client.erl`, has **an extremely simple** method for dealing
|
|
||||||
with failed servers. I know it's simple and dumb, but that's OK in
|
|
||||||
many cases.
|
|
||||||
|
|
||||||
However, `basho_bench` and the `machi_cr_client.erl` were acting very,
|
|
||||||
very badly. I couldn't figure it out until I took a peek at my OS's
|
|
||||||
`dmesg` output, namely: `dmesg | tail`. It said things like this:
|
|
||||||
|
|
||||||
Limiting closed port RST response from 690 to 50 packets per second
|
|
||||||
Limiting closed port RST response from 367 to 50 packets per second
|
|
||||||
Limiting closed port RST response from 101 to 50 packets per second
|
|
||||||
Limiting closed port RST response from 682 to 50 packets per second
|
|
||||||
Limiting closed port RST response from 467 to 50 packets per second
|
|
||||||
|
|
||||||
Well, isn't that interesting?
|
|
||||||
|
|
||||||
This system was running on a single OS X machine: my MacBook Pro
|
|
||||||
laptop, running OS X 10.10 (Yosemite). I have seen that error
|
|
||||||
before. And I know how to fix it.
|
|
||||||
|
|
||||||
* **Option 1**: Change the client library config to ignore the Machi
|
|
||||||
servers that I know will always be down during my experiment.
|
|
||||||
* ** Option 2**: Use the following to change my OS's TCP stack RST
|
|
||||||
behavior. (If a TCP port is not being listened to, the OS will
|
|
||||||
send a RST packet to signal "connection refused".)
|
|
||||||
|
|
||||||
On OS X, the limit for RST packets is 50/second. The
|
|
||||||
`machi_cr_client.erl` client can generate far more than 50/second, as
|
|
||||||
the `Limiting closed port RST response...` messages above show. So, I
|
|
||||||
used some brute-force to change the environment:
|
|
||||||
|
|
||||||
sudo sysctl -w net.inet.icmp.icmplim=20000
|
|
||||||
|
|
||||||
... and the problem disappeared.
|
|
||||||
|
|
||||||
## Starting with basho_bench: a step-by-step tutorial
|
|
||||||
|
|
||||||
First, clone the `basho_bench` source code, then compile it. You will
|
|
||||||
need Erlang/OTP version R16B or later to compile. I recommend using
|
|
||||||
Erlang/OTP 17.x, because I've been doing my Machi development using
|
|
||||||
17.x.
|
|
||||||
|
|
||||||
cd /some/nice/dev/place
|
|
||||||
git clone https://github.com/basho/basho_bench.git
|
|
||||||
cd basho_bench
|
|
||||||
make
|
|
||||||
|
|
||||||
In order to create graphs of `basho_bench` output, you'll need
|
|
||||||
installed one of the following:
|
|
||||||
|
|
||||||
* R (the statistics package)
|
|
||||||
* gnuplot
|
|
||||||
|
|
||||||
If you don't have either available on the machine(s) you're testing,
|
|
||||||
but you do have R (or gnuplot) on some other machine **Y**, then you can
|
|
||||||
copy the output files to machine **Y** and generate the graphs there.
|
|
||||||
|
|
||||||
## Compiling the Machi source
|
|
||||||
|
|
||||||
First, clone the Machi source code, then compile it. You will
|
|
||||||
need Erlang/OTP version 17.x to compile.
|
|
||||||
|
|
||||||
cd /some/nice/dev/place
|
|
||||||
git clone https://github.com/basho/machi.git
|
|
||||||
cd machi
|
|
||||||
make
|
|
||||||
|
|
||||||
## Creating a basho_bench test configuration file.
|
|
||||||
|
|
||||||
There are a couple of example `basho_bench` configuration files in the
|
|
||||||
Machi `priv` directory.
|
|
||||||
|
|
||||||
* [basho_bench.append-example.config](priv/basho_bench.append-example.config),
|
|
||||||
an example for writing Machi files.
|
|
||||||
* [basho_bench.read-example.config](priv/basho_bench.read-example.config),
|
|
||||||
an example for reading Machi files.
|
|
||||||
|
|
||||||
If you want a test to do both reading & writing ... well, the
|
|
||||||
driver/plug-in is not mature enough to do it **well**. If you really
|
|
||||||
want to, refer to the `basho_bench` docs for how to use the
|
|
||||||
`operations` config option.
|
|
||||||
|
|
||||||
The `basho_bench` config file is configured in Erlang term format.
|
|
||||||
Each configuration item is a 2-tuple followed by a period. Comments
|
|
||||||
begin with a `%` character and continue to the end-of-line.
|
|
||||||
|
|
||||||
%% Mandatory: adjust this code path to top of your compiled Machi source distro
|
|
||||||
{code_paths, ["/Users/fritchie/b/src/machi"]}.
|
|
||||||
{driver, machi_basho_bench_driver}.
|
|
||||||
|
|
||||||
%% Chose your maximum rate (per worker proc, see 'concurrent' below)
|
|
||||||
{mode, {rate, 25}}.
|
|
||||||
|
|
||||||
%% Runtime & reporting interval
|
|
||||||
{duration, 10}. % minutes
|
|
||||||
{report_interval, 1}. % seconds
|
|
||||||
|
|
||||||
%% Choose your number of worker procs
|
|
||||||
{concurrent, 5}.
|
|
||||||
|
|
||||||
%% Here's a chain of (up to) length 3, all on localhost
|
|
||||||
{machi_server_info,
|
|
||||||
[
|
|
||||||
{p_srvr,a,machi_flu1_client,"localhost",4444,[]},
|
|
||||||
{p_srvr,b,machi_flu1_client,"localhost",4445,[]},
|
|
||||||
{p_srvr,c,machi_flu1_client,"localhost",4446,[]}
|
|
||||||
]}.
|
|
||||||
{machi_ets_key_tab_type, set}. % 'set' or 'ordered_set'
|
|
||||||
|
|
||||||
%% Workload-specific definitions follow....
|
|
||||||
|
|
||||||
%% 10 parts 'append' operation + 0 parts anything else = 100% 'append' ops
|
|
||||||
{operations, [{append, 10}]}.
|
|
||||||
|
|
||||||
%% For append, key = Machi file prefix name
|
|
||||||
{key_generator, {concat_binary, <<"prefix">>,
|
|
||||||
{to_binstr, "~w", {uniform_int, 30}}}}.
|
|
||||||
|
|
||||||
%% Increase size of value_generator_source_size if value_generator is big!!
|
|
||||||
{value_generator_source_size, 2111000}.
|
|
||||||
{value_generator, {fixed_bin, 32768}}. % 32 KB
|
|
||||||
|
|
||||||
In summary:
|
|
||||||
|
|
||||||
* Yes, you really need to change `code_paths` to be the same as your
|
|
||||||
`/some/nice/dev/place/basho_bench` directory ... and that directory
|
|
||||||
must be on the same machine(s) that you intend to run `basho_bench`.
|
|
||||||
* Each worker process will have a rate limit of 25 ops/sec.
|
|
||||||
* The test will run for 10 minutes and report stats every 1 second.
|
|
||||||
* There are 5 concurrent worker processes. Each worker will
|
|
||||||
concurrently issue commands from the `operations` list, within the
|
|
||||||
workload throttle limit.
|
|
||||||
* The Machi cluster is a collection of three servers, all on
|
|
||||||
"localhost", and using TCP ports 4444-4446.
|
|
||||||
* Don't change the `machi_ets_key_tab_type`
|
|
||||||
* Our workload operation mix is 100% `append` operations.
|
|
||||||
* The key generator for the `append` operation specifies the file
|
|
||||||
prefix that will be chosen (at pseudo-random). In this case, we'll
|
|
||||||
choose uniformly randomly between file prefix `prefix0` and
|
|
||||||
`prefix29`.
|
|
||||||
* The values that we append will be fixed 32KB length, but they will
|
|
||||||
be chosen from a random byte string of 2,111,000 bytes.
|
|
||||||
|
|
||||||
There are many other options for `basho_bench`, especially for the
|
|
||||||
`key_generator` and `value_generator` options. Please see the
|
|
||||||
`basho_bench` docs for further information.
|
|
||||||
|
|
||||||
## Running basho_bench
|
|
||||||
|
|
||||||
You can run `basho_bench` using the command:
|
|
||||||
|
|
||||||
/some/nice/dev/place/basho_bench/basho_bench /path/to/config/file
|
|
||||||
|
|
||||||
... where `/path/to/config/file` is the path to your config file. (If
|
|
||||||
you use an example from the `priv` dir, we recommend that you make a
|
|
||||||
copy elsewhere, edit the copy, and then use the copy to run
|
|
||||||
`basho_bench`.)
|
|
||||||
|
|
||||||
You'll create a stats output directory, called `tests`, in the current
|
|
||||||
working directory. (Add `{results_dir, "/some/output/dir"}.` to change
|
|
||||||
the default!)
|
|
||||||
|
|
||||||
Each time `basho_bench` is run, a new output stats directory is
|
|
||||||
created in the `tests` directory. The symbolic link `tests/current`
|
|
||||||
will always point to the last `basho_bench` run's output. But all
|
|
||||||
prior results are always accessible! Take a look in this directory
|
|
||||||
for all of the output.
|
|
||||||
|
|
||||||
## Generating some pretty graphs
|
|
||||||
|
|
||||||
If you are using R, then the following command will create a graph:
|
|
||||||
|
|
||||||
Rscript --vanilla /some/nice/dev/place/basho_bench/basho_bench/priv/summary.r -i $CWD/tests/current
|
|
||||||
|
|
||||||
If the `tests` directory is not in your current working dir (i.e. not
|
|
||||||
in `$CWD`), then please alter the command accordingly.
|
|
||||||
|
|
||||||
R will create the final results graph in `$CWD/tests/current/summary.png`.
|
|
||||||
|
|
||||||
If you are using gnuplot, please look at
|
|
||||||
`/some/nice/dev/place/basho_bench/basho_bench/Makefile` to see how to
|
|
||||||
use gnuplot to create the final results graph.
|
|
||||||
|
|
||||||
## An example graph
|
|
||||||
|
|
||||||
So, without a lot of context about the **Machi system** or about the
|
|
||||||
**basho_bench system** or about the ops being performed, here is an
|
|
||||||
example graph that was created by R:
|
|
||||||
|
|
||||||
![](https://basho.github.io/machi/images/basho_bench.example0.png)
|
|
||||||
|
|
||||||
**Without context??* How do I remember the context?
|
|
||||||
|
|
||||||
My recommendation is: always keep the `.config` file together with the
|
|
||||||
graph file. In the `tests` directory, `basho_bench` will always make
|
|
||||||
a copy of the config file used to generate the test data.
|
|
||||||
|
|
||||||
This config tells you very little about the environment of the load
|
|
||||||
generator machine or the Machi cluster, but ... you need to maintain
|
|
||||||
that documentation yourself, please! You'll thank me for that advice,
|
|
||||||
someday, 11 months from now when you can't remember the details of
|
|
||||||
that important test that you ran so very long ago.
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
Really, we don't recommend using `basho_bench` for any serious
|
|
||||||
performance measurement of Machi yet: Machi needs more maturity before
|
|
||||||
it's reasonable to measure & judge its performance. But stress
|
|
||||||
testing is indeed useful for reasons other than measuring
|
|
||||||
Nth-percentile latency of operation `flarfbnitz`. We hope that this
|
|
||||||
tutorial has been helpful!
|
|
||||||
|
|
||||||
If you encounter any difficulty with this tutorial or with Machi,
|
|
||||||
please open an issue/ticket at [GH Issues for
|
|
||||||
Machi](https://github.com/basho/machi/issues) ... use the green "New
|
|
||||||
issue" button. There are bugs and misfeatures in the `basho_bench`
|
|
||||||
plugin, sorry, but please help us fix them.
|
|
||||||
|
|
||||||
> -Scott Lystig Fritchie,
|
|
||||||
> Machi Team @ Basho
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,251 +0,0 @@
|
||||||
-*- mode: org; -*-
|
|
||||||
#+TITLE: Machi Chain Self-Management Sketch
|
|
||||||
#+AUTHOR: Scott
|
|
||||||
#+STARTUP: lognotedone hidestars indent showall inlineimages
|
|
||||||
#+SEQ_TODO: TODO WORKING WAITING DONE
|
|
||||||
|
|
||||||
* 1. Abstract
|
|
||||||
The high level design of the Machi "chain manager" has moved to the
|
|
||||||
[[high-level-chain-manager.pdf][Machi chain manager high level design]] document.
|
|
||||||
|
|
||||||
We try to discuss the network partition simulator that the
|
|
||||||
algorithm runs in and how the algorithm behaves in both symmetric and
|
|
||||||
asymmetric network partition scenarios. The symmetric partition cases
|
|
||||||
are all working well (surprising in a good way), and the asymmetric
|
|
||||||
partition cases are working well (in a damn mystifying kind of way).
|
|
||||||
It'd be really, *really* great to get more review of the algorithm and
|
|
||||||
the simulator.
|
|
||||||
|
|
||||||
* 2. Copyright
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
%% Copyright (c) 2015 Basho Technologies, Inc. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% This file is provided to you under the Apache License,
|
|
||||||
%% Version 2.0 (the "License"); you may not use this file
|
|
||||||
%% except in compliance with the License. You may obtain
|
|
||||||
%% a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing,
|
|
||||||
%% software distributed under the License is distributed on an
|
|
||||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
%% KIND, either express or implied. See the License for the
|
|
||||||
%% specific language governing permissions and limitations
|
|
||||||
%% under the License.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
|
|
||||||
* 3. Document restructuring
|
|
||||||
|
|
||||||
Much of the text previously appearing in this document has moved to the
|
|
||||||
[[high-level-chain-manager.pdf][Machi chain manager high level design]] document.
|
|
||||||
|
|
||||||
* 4. Diagram of the self-management algorithm
|
|
||||||
|
|
||||||
** WARNING: This section is now deprecated
|
|
||||||
|
|
||||||
The definitive text for this section has moved to the [[high-level-chain-manager.pdf][Machi chain
|
|
||||||
manager high level design]] document.
|
|
||||||
|
|
||||||
** Flowchart notes
|
|
||||||
|
|
||||||
*** Algorithm execution rates / sleep intervals between executions
|
|
||||||
|
|
||||||
Due to the ranking algorithm's preference for author node names that
|
|
||||||
are large (lexicographically), nodes with larger node names should
|
|
||||||
execute the algorithm more frequently than other nodes. The reason
|
|
||||||
for this is to try to avoid churn: a proposal by a "small" node may
|
|
||||||
propose a UPI list of L at epoch 10, and a few moments later a "big"
|
|
||||||
node may propose the same UPI list L at epoch 11. In this case, there
|
|
||||||
would be two chain state transitions: the epoch 11 projection would be
|
|
||||||
ranked higher than epoch 10's projection. If the "big" node
|
|
||||||
executed more frequently than the "small" node, then it's more likely
|
|
||||||
that epoch 10 would be written by the "big" node, which would then
|
|
||||||
cause the "small" node to stop at state A40 and avoid any
|
|
||||||
externally-visible action.
|
|
||||||
|
|
||||||
*** A simple example race between two participants noting a 3rd's failure
|
|
||||||
|
|
||||||
Assume a chain of three nodes, A, B, and C. In a projection at epoch
|
|
||||||
E. For all nodes, the P_current projection at epoch E is:
|
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
|
||||||
UPI=[A,B,C], Repairing=[], Down=[]
|
|
||||||
#+END_QUOTE
|
|
||||||
|
|
||||||
Now assume that C crashes during epoch E. The failure detector
|
|
||||||
running locally at both A & B eventually notice C's death. The new
|
|
||||||
information triggers a new iteration of the self-management algorithm.
|
|
||||||
A calculates its P_newprop (call it P_newprop_a) and writes it to its
|
|
||||||
own public projection store. Meanwhile, B does the same and wins the
|
|
||||||
race to write P_newprop_b to its own public projection store.
|
|
||||||
|
|
||||||
At this instant in time, the public projection stores of each node
|
|
||||||
looks something like this:
|
|
||||||
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
| Epoch | Node A | Node B | Node C |
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
| E | UPI=[A,B,C] | UPI=[A,B,C] | UPI=[A,B,C] |
|
|
||||||
| | Repairing=[] | Repairing=[] | Repairing=[] |
|
|
||||||
| | Down=[] | Down=[] | Down=[] |
|
|
||||||
| | Author=A | Author=A | Author=A |
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
| E+1 | UPI=[A,B] | UPI=[A,B] | C is dead, |
|
|
||||||
| | Repairing=[] | Repairing=[] | unwritten |
|
|
||||||
| | Down=[C] | Down=[C] | |
|
|
||||||
| | Author=A | Author=B | |
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
|
|
||||||
If we use the CORFU-style projection naming convention, where a
|
|
||||||
projection's name is exactly equal to the epoch number, then all
|
|
||||||
participants cannot tell the difference between the projection at
|
|
||||||
epoch E+1 authored by node A from the projection at epoch E+1 authored
|
|
||||||
by node B: the names are the same, i.e., E+1.
|
|
||||||
|
|
||||||
Machi must extend the original CORFU protocols by changing the name of
|
|
||||||
the projection. In Machi's case, the projection is named by this
|
|
||||||
2-tuple:
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{epoch #, hash of the entire projection (minus hash field itself)}
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
This name is used in all relevant APIs where the name is required to
|
|
||||||
make a wedge state transition. In the case of the example & table
|
|
||||||
above, all of the UPI & Repairing & Down lists are equal. However, A
|
|
||||||
& B's unanimity is due to the symmetric nature of C's partition: C is
|
|
||||||
dead. In the case of an asymmetric partition of C, it is indeed
|
|
||||||
possible for A's version of epoch E+1's UPI list to be different from
|
|
||||||
B's UPI list in the same epoch E+1.
|
|
||||||
|
|
||||||
*** A second example, building on the first example
|
|
||||||
|
|
||||||
Building on the first example, let's assume that A & B have reconciled
|
|
||||||
their proposals for epoch E+2. Nodes A & B are running under a
|
|
||||||
unanimous proposal at E+2.
|
|
||||||
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
| E+2 | UPI=[A,B] | UPI=[A,B] | C is dead, |
|
|
||||||
| | Repairing=[] | Repairing=[] | unwritten |
|
|
||||||
| | Down=[C] | Down=[C] | |
|
|
||||||
| | Author=A | Author=A | |
|
|
||||||
|-------+--------------+--------------+--------------|
|
|
||||||
|
|
||||||
Now assume that C restarts. It was dead for a little while, and its
|
|
||||||
code is slightly buggy. Node C decides to make a proposal without
|
|
||||||
first consulting its failure detector: let's assume that C believes
|
|
||||||
that only C is alive. Also, C knows that epoch E was the last epoch
|
|
||||||
valid before it crashed, so it decides that it will write its new
|
|
||||||
proposal at E+2. The result is a set of public projection stores that
|
|
||||||
look like this:
|
|
||||||
|
|
||||||
|-----+--------------+--------------+--------------|
|
|
||||||
| E+2 | UPI=[A,B] | UPI=[A,B] | UPI=[C] |
|
|
||||||
| | Repairing=[] | Repairing=[] | Repairing=[] |
|
|
||||||
| | Down=[C] | Down=[C] | Down=[A,B] |
|
|
||||||
| | Author=A | Author=A | Author=C |
|
|
||||||
|-----+--------------+--------------+--------------|
|
|
||||||
|
|
||||||
Now we're in a pickle where a client C could read the latest
|
|
||||||
projection from node C and get a different view of the world than if
|
|
||||||
it had read the latest projection from nodes A or B.
|
|
||||||
|
|
||||||
If running in AP mode, this wouldn't be a big problem: a write to node
|
|
||||||
C only (or a write to nodes A & B only) would be reconciled
|
|
||||||
eventually. Also, eventually, one of the nodes would realize that C
|
|
||||||
was no longer partitioned and would make a new proposal at epoch E+3.
|
|
||||||
|
|
||||||
If running in CP mode, then any client that attempted to use C's
|
|
||||||
version of the E+2 projection would fail: the UPI list does not
|
|
||||||
contain a quorum majority of nodes. (Other discussion of CP mode's
|
|
||||||
use of quorum majority for UPI members is out of scope of this
|
|
||||||
document. Also out of scope is the use of "witness servers" to
|
|
||||||
augment the quorum majority UPI scheme.)
|
|
||||||
|
|
||||||
* 5. The Network Partition Simulator
|
|
||||||
** Overview
|
|
||||||
The function machi_chain_manager1_test:convergence_demo_test()
|
|
||||||
executes the following in a simulated network environment within a
|
|
||||||
single Erlang VM:
|
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
|
||||||
Test the convergence behavior of the chain self-management algorithm
|
|
||||||
for Machi.
|
|
||||||
|
|
||||||
1. Set up 4 FLUs and chain manager pairs.
|
|
||||||
|
|
||||||
2. Create a number of different network partition scenarios, where
|
|
||||||
(simulated) partitions may be symmetric or asymmetric. (At the
|
|
||||||
Seattle 2015 meet-up, I called this the "shaking the snow globe"
|
|
||||||
phase, where asymmetric network partitions are simulated and are
|
|
||||||
calculated at random differently for each simulated node. During
|
|
||||||
this time, the simulated network is wildly unstable.)
|
|
||||||
|
|
||||||
3. Then halt changing the partitions and keep the simulated network
|
|
||||||
stable. The simulated may remain broken (i.e. at least one
|
|
||||||
asymmetric partition remains in effect), but at least it's
|
|
||||||
stable.
|
|
||||||
|
|
||||||
4. Run a number of iterations of the algorithm in parallel by poking
|
|
||||||
each of the manager processes on a random'ish basis to simulate
|
|
||||||
the passage of time.
|
|
||||||
|
|
||||||
5. Afterward, fetch the chain transition histories made by each FLU
|
|
||||||
and verify that no transition was ever unsafe.
|
|
||||||
#+END_QUOTE
|
|
||||||
|
|
||||||
|
|
||||||
** Behavior in symmetric network partitions
|
|
||||||
|
|
||||||
The simulator has yet to find an error. This is both really cool and
|
|
||||||
really terrifying: is this *really* working? No, seriously, where are
|
|
||||||
the bugs? Good question. Both the algorithm and the simulator need
|
|
||||||
review and futher study.
|
|
||||||
|
|
||||||
In fact, it'd be awesome if I could work with someone who has more
|
|
||||||
TLA+ experience than I do to work on a formal specification of the
|
|
||||||
self-management algorithm and verify its correctness.
|
|
||||||
|
|
||||||
** Behavior in asymmetric network partitions
|
|
||||||
|
|
||||||
Text has moved to the [[high-level-chain-manager.pdf][Machi chain manager high level design]] document.
|
|
||||||
|
|
||||||
* Prototype notes
|
|
||||||
|
|
||||||
** Mid-April 2015
|
|
||||||
|
|
||||||
I've finished moving the chain manager plus the inner/nested
|
|
||||||
projection code into the top-level 'src' dir of this repo. The idea
|
|
||||||
is working very well under simulation, more than well enough to gamble
|
|
||||||
on for initial use.
|
|
||||||
|
|
||||||
Stronger validation work will continue through 2015, ideally using a
|
|
||||||
tool like TLA+.
|
|
||||||
|
|
||||||
** Mid-March 2015
|
|
||||||
|
|
||||||
I've come to realize that the property that causes the nice property
|
|
||||||
of "Were my last 2L proposals identical?" also requires that the
|
|
||||||
proposals be *stable*. If a participant notices, "Hey, there's
|
|
||||||
flapping happening, so I'll propose a different projection
|
|
||||||
P_different", then the very act of proposing P_different disrupts the
|
|
||||||
"last 2L proposals identical" cycle the enables us to detect
|
|
||||||
flapping. We kill the goose that's laying our golden egg.
|
|
||||||
|
|
||||||
I've been working on the idea of "nested" projections, namely an
|
|
||||||
"outer" and "inner" projection. Only the "outer projection" is used
|
|
||||||
for cycle detection. The "inner projection" is the same as the outer
|
|
||||||
projection when flapping is not detected. When flapping is detected,
|
|
||||||
then the inner projection is one that excludes all nodes that the
|
|
||||||
outer projection has identified as victims of asymmetric partition.
|
|
||||||
|
|
||||||
This inner projection technique may or may not work well enough to
|
|
||||||
use? It would require constant flapping of the outer proposal, which
|
|
||||||
is going to consume CPU and also chew up projection store keys with
|
|
||||||
the flapping churn. That churn would continue as long as an
|
|
||||||
asymmetric partition exists. The simplest way to cope with this would
|
|
||||||
be to reduce proposal rates significantly, say 10x or 50x slower, to
|
|
||||||
slow churn down to proposals from several-per-second to perhaps
|
|
||||||
several-per-minute?
|
|
|
@ -1,103 +0,0 @@
|
||||||
#FIG 3.2 Produced by xfig version 3.2.5b
|
|
||||||
Landscape
|
|
||||||
Center
|
|
||||||
Inches
|
|
||||||
Letter
|
|
||||||
94.00
|
|
||||||
Single
|
|
||||||
-2
|
|
||||||
1200 2
|
|
||||||
6 7425 2700 8700 3300
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 645 7425 2895 After\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 255 1215 7425 3210 Migration\001
|
|
||||||
-6
|
|
||||||
6 7425 450 8700 1050
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 780 7425 675 Before\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 255 1215 7425 990 Migration\001
|
|
||||||
-6
|
|
||||||
6 75 1425 6900 2325
|
|
||||||
6 4875 1425 6900 2325
|
|
||||||
6 5400 1575 6375 2175
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 165 390 5400 1800 Not\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 225 945 5400 2100 migrated\001
|
|
||||||
-6
|
|
||||||
2 2 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5
|
|
||||||
4950 1500 6825 1500 6825 2250 4950 2250 4950 1500
|
|
||||||
-6
|
|
||||||
6 2475 1425 4500 2325
|
|
||||||
6 3000 1575 3975 2175
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 165 390 3000 1800 Not\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 225 945 3000 2100 migrated\001
|
|
||||||
-6
|
|
||||||
2 2 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5
|
|
||||||
2550 1500 4425 1500 4425 2250 2550 2250 2550 1500
|
|
||||||
-6
|
|
||||||
6 75 1425 2100 2325
|
|
||||||
6 600 1575 1575 2175
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 165 390 600 1800 Not\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 225 945 600 2100 migrated\001
|
|
||||||
-6
|
|
||||||
2 2 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5
|
|
||||||
150 1500 2025 1500 2025 2250 150 2250 150 1500
|
|
||||||
-6
|
|
||||||
-6
|
|
||||||
2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2
|
|
||||||
1 1 3.00 60.00 120.00
|
|
||||||
150 4200 150 3750
|
|
||||||
2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2
|
|
||||||
1 1 3.00 60.00 120.00
|
|
||||||
3750 4200 3750 3750
|
|
||||||
2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2
|
|
||||||
1 1 3.00 60.00 120.00
|
|
||||||
2025 4200 2025 3750
|
|
||||||
2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2
|
|
||||||
1 1 3.00 60.00 120.00
|
|
||||||
7350 4200 7350 3750
|
|
||||||
2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2
|
|
||||||
1 1 3.00 60.00 120.00
|
|
||||||
5550 4200 5550 3750
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
2550 0 2550 1500 150 1500 150 0 2550 0
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
4950 0 4950 1500 2550 1500 2550 0 4950 0
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
7350 0 7350 1500 4950 1500 4950 0 7350 0
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
150 2250 2025 2250 2025 3750 150 3750 150 2250
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
4425 2250 4950 2250 4950 3750 4425 3750 4425 2250
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
4950 2250 6825 2250 6825 3750 4950 3750 4950 2250
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
6825 2250 7350 2250 7350 3750 6825 3750 6825 2250
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
2025 2250 2550 2250 2550 3750 2025 3750 2025 2250
|
|
||||||
2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
|
||||||
2550 2250 4425 2250 4425 3750 2550 3750 2550 2250
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 480 75 4500 0.00\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 480 6825 4500 1.00\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 480 1725 4500 0.25\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 480 3525 4500 0.50\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 195 480 5250 4500 0.75\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 450 1275 ~33% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 2925 1275 ~33% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 5250 1275 ~33% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 180 495 2025 3525 ~8%\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 300 3525 ~25% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 2625 3525 ~25% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 180 495 4425 3525 ~8%\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 240 1710 5025 3525 ~25% total keys\001
|
|
||||||
4 0 0 50 -1 2 14 0.0000 4 180 495 6825 3525 ~8%\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 195 2175 3075 4\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 195 4575 3075 4\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 195 6975 3075 4\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 600 600 Chain1\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 3000 600 Chain2\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 5400 600 Chain3\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 285 2100 2625 C\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 285 4500 2625 C\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 285 6900 2625 C\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 525 2850 Chain1\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 2925 2850 Chain2\001
|
|
||||||
4 0 0 50 -1 2 24 0.0000 4 270 1245 5325 2850 Chain3\001
|
|
||||||
4 0 0 50 -1 2 18 0.0000 4 240 4350 1350 4875 Cluster locator, on the unit interval\001
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
|
@ -1,481 +0,0 @@
|
||||||
-*- mode: org; -*-
|
|
||||||
#+TITLE: Machi cluster "name game" sketch
|
|
||||||
#+AUTHOR: Scott
|
|
||||||
#+STARTUP: lognotedone hidestars indent showall inlineimages
|
|
||||||
#+SEQ_TODO: TODO WORKING WAITING DONE
|
|
||||||
#+COMMENT: M-x visual-line-mode
|
|
||||||
#+COMMENT: Also, disable auto-fill-mode
|
|
||||||
|
|
||||||
* 1. "Name Games" with random-slicing style consistent hashing
|
|
||||||
|
|
||||||
Our goal: to distribute lots of files very evenly across a large
|
|
||||||
collection of individual, small Machi chains.
|
|
||||||
|
|
||||||
* 2. Assumptions
|
|
||||||
|
|
||||||
** Basic familiarity with Machi high level design and Machi's "projection"
|
|
||||||
|
|
||||||
The [[https://github.com/basho/machi/blob/master/doc/high-level-machi.pdf][Machi high level design document]] contains all of the basic
|
|
||||||
background assumed by the rest of this document.
|
|
||||||
|
|
||||||
** Analogy: "neighborhood : city :: Machi chain : Machi cluster"
|
|
||||||
|
|
||||||
Analogy: The word "machi" in Japanese means small town or
|
|
||||||
neighborhood. As the Tokyo Metropolitan Area is built from many
|
|
||||||
machis and smaller cities, therefore a big, partitioned file store can
|
|
||||||
be built out of many small Machi chains.
|
|
||||||
|
|
||||||
** Familiarity with the Machi chain concept
|
|
||||||
|
|
||||||
It's clear (I hope!) from
|
|
||||||
the [[https://github.com/basho/machi/blob/master/doc/high-level-machi.pdf][Machi high level design document]] that Machi alone does not support
|
|
||||||
any kind of file partitioning/distribution/sharding across multiple
|
|
||||||
small Machi chains. There must be another layer above a Machi chain to
|
|
||||||
provide such partitioning services.
|
|
||||||
|
|
||||||
Using the [[https://github.com/basho/machi/tree/master/prototype/demo-day-hack][cluster quick-and-dirty prototype]] as an
|
|
||||||
architecture sketch, let's now assume that we have ~n~ independent Machi
|
|
||||||
chains. We assume that each of these chains has the same
|
|
||||||
chain length in the nominal case, e.g. chain length of 3.
|
|
||||||
We wish to provide partitioned/distributed file storage
|
|
||||||
across all ~n~ chains. We call the entire collection of ~n~ Machi
|
|
||||||
chains a "cluster".
|
|
||||||
|
|
||||||
We may wish to have several types of Machi clusters. For example:
|
|
||||||
|
|
||||||
+ Chain length of 1 for "don't care if it gets lost,
|
|
||||||
store stuff very very cheaply" data.
|
|
||||||
+ Chain length of 2 for normal data.
|
|
||||||
+ Equivalent to quorum replication's reliability with 3 copies.
|
|
||||||
+ Chain length of 7 for critical, unreplaceable data.
|
|
||||||
+ Equivalent to quorum replication's reliability with 15 copies.
|
|
||||||
|
|
||||||
Each of these types of chains will have a name ~N~ in the
|
|
||||||
namespace. The role of the cluster namespace will be demonstrated in
|
|
||||||
Section 3 below.
|
|
||||||
|
|
||||||
** Continue an early assumption: a Machi chain is unaware of clustering
|
|
||||||
|
|
||||||
Let's continue with an assumption that an individual Machi chain
|
|
||||||
inside of a cluster is completely unaware of the cluster layer.
|
|
||||||
|
|
||||||
** The reader is familiar with the random slicing technique
|
|
||||||
|
|
||||||
I'd done something very-very-nearly-like-this for the Hibari database
|
|
||||||
6 years ago. But the Hibari technique was based on stuff I did at
|
|
||||||
Sendmail, Inc, in 2000, so this technique feels like old news to me.
|
|
||||||
{shrug}
|
|
||||||
|
|
||||||
The following section provides an illustrated example.
|
|
||||||
Very quickly, the random slicing algorithm is:
|
|
||||||
|
|
||||||
- Hash a string onto the unit interval [0.0, 1.0)
|
|
||||||
- Calculate h(unit interval point, Map) -> bin, where ~Map~ divides
|
|
||||||
the unit interval into bins (or partitions or shards).
|
|
||||||
|
|
||||||
Machi's adaptation is in step 1: we do not hash any strings. Instead, we
|
|
||||||
simply choose a number on the unit interval. This number is called
|
|
||||||
the "cluster locator number".
|
|
||||||
|
|
||||||
As described later in this doc, Machi file names are structured into
|
|
||||||
several components. One component of the file name contains the cluster
|
|
||||||
locator number; we use the number as-is for step 2 above.
|
|
||||||
|
|
||||||
*** For more information about Random Slicing
|
|
||||||
|
|
||||||
For a comprehensive description of random slicing, please see the
|
|
||||||
first two papers. For a quicker summary, please see the third
|
|
||||||
reference.
|
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
|
||||||
Reliable and Randomized Data Distribution Strategies for Large Scale Storage Systems
|
|
||||||
Alberto Miranda et al.
|
|
||||||
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.226.5609
|
|
||||||
(short version, HIPC'11)
|
|
||||||
|
|
||||||
Random Slicing: Efficient and Scalable Data Placement for Large-Scale
|
|
||||||
Storage Systems
|
|
||||||
Alberto Miranda et al.
|
|
||||||
DOI: http://dx.doi.org/10.1145/2632230 (long version, ACM Transactions
|
|
||||||
on Storage, Vol. 10, No. 3, Article 9, 2014)
|
|
||||||
|
|
||||||
[[http://hibari.github.io/hibari-doc/hibari-sysadmin-guide.en.html#chain-migration][Hibari Sysadmin Guide, chain migration section]].
|
|
||||||
http://hibari.github.io/hibari-doc/hibari-sysadmin-guide.en.html#chain-migration
|
|
||||||
#+END_QUOTE
|
|
||||||
|
|
||||||
* 3. A simple illustration
|
|
||||||
|
|
||||||
We use a variation of the Random Slicing hash that we will call
|
|
||||||
~rs_hash_with_float()~. The Erlang-style function type is shown
|
|
||||||
below.
|
|
||||||
|
|
||||||
#+BEGIN_SRC erlang
|
|
||||||
%% type specs, Erlang-style
|
|
||||||
-spec rs_hash_with_float(float(), rs_hash:map()) -> rs_hash:chain_id().
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
I'm borrowing an illustration from the HibariDB documentation here,
|
|
||||||
but it fits my purposes quite well. (I am the original creator of that
|
|
||||||
image, and also the use license is compatible.)
|
|
||||||
|
|
||||||
#+CAPTION: Illustration of 'Map', using four Machi chains
|
|
||||||
|
|
||||||
[[./migration-4.png]]
|
|
||||||
|
|
||||||
Assume that we have a random slicing map called ~Map~. This particular
|
|
||||||
~Map~ maps the unit interval onto 4 Machi chains:
|
|
||||||
|
|
||||||
| Hash range | Chain ID |
|
|
||||||
|-------------+----------|
|
|
||||||
| 0.00 - 0.25 | Chain1 |
|
|
||||||
| 0.25 - 0.33 | Chain4 |
|
|
||||||
| 0.33 - 0.58 | Chain2 |
|
|
||||||
| 0.58 - 0.66 | Chain4 |
|
|
||||||
| 0.66 - 0.91 | Chain3 |
|
|
||||||
| 0.91 - 1.00 | Chain4 |
|
|
||||||
|
|
||||||
Assume that the system chooses a cluster locator of 0.05.
|
|
||||||
According to ~Map~, the value of
|
|
||||||
~rs_hash_with_float(0.05,Map) = Chain1~.
|
|
||||||
Similarly, ~rs_hash_with_float(0.26,Map) = Chain4~.
|
|
||||||
|
|
||||||
This example should look very similar to Hibari's technique.
|
|
||||||
The Hibari documentation has a brief photo illustration of how random
|
|
||||||
slicing works, see [[http://hibari.github.io/hibari-doc/hibari-sysadmin-guide.en.html#chain-migration][Hibari Sysadmin Guide, chain migration]].
|
|
||||||
|
|
||||||
* 4. Use of the cluster namespace: name separation plus chain type
|
|
||||||
|
|
||||||
Let us assume that the cluster framework provides several different types
|
|
||||||
of chains:
|
|
||||||
|
|
||||||
| Chain length | Namespace | Consistency Mode | Comment |
|
|
||||||
|--------------+--------------+------------------+----------------------------------|
|
|
||||||
| 3 | ~normal~ | eventual | Normal storage redundancy & cost |
|
|
||||||
| 2 | ~reduced~ | eventual | Reduced cost storage |
|
|
||||||
| 1 | ~risky~ | eventual | Really, really cheap storage |
|
|
||||||
| 7 | ~paranoid~ | eventual | Safety-critical storage |
|
|
||||||
| 3 | ~sequential~ | strong | Strong consistency |
|
|
||||||
|--------------+--------------+------------------+----------------------------------|
|
|
||||||
|
|
||||||
The client may want to choose the amount of redundancy that its
|
|
||||||
application requires: normal, reduced cost, or perhaps even a single
|
|
||||||
copy. The cluster namespace is used by the client to signal this
|
|
||||||
intention.
|
|
||||||
|
|
||||||
Further, the cluster administrators may wish to use the namespace to
|
|
||||||
provide separate storage for different applications. Jane's
|
|
||||||
application may use the namespace "jane-normal" and Bob's app uses
|
|
||||||
"bob-reduced". Administrators may definine separate groups of
|
|
||||||
chains on separate servers to serve these two applications.
|
|
||||||
|
|
||||||
* 5. In its lifetime, a file may be moved to different chains
|
|
||||||
|
|
||||||
The cluster management scheme may decide that files need to migrate to
|
|
||||||
other chains -- i.e., file that is initially created on chain ID ~X~
|
|
||||||
has been moved to chain ID ~Y~.
|
|
||||||
|
|
||||||
+ For storage load or I/O load balancing reasons.
|
|
||||||
+ Because a chain is being decommissioned by the sysadmin.
|
|
||||||
|
|
||||||
* 6. Floating point is not required ... it is merely convenient for explanation
|
|
||||||
|
|
||||||
NOTE: Use of floating point terms is not required. For example,
|
|
||||||
integer arithmetic could be used, if using a sufficiently large
|
|
||||||
interval to create an even & smooth distribution of hashes across the
|
|
||||||
expected maximum number of chains.
|
|
||||||
|
|
||||||
For example, if the maximum cluster size would be 4,000 individual
|
|
||||||
Machi chains, then a minimum of 12 bits of integer space is required
|
|
||||||
to assign one integer per Machi chain. However, for load balancing
|
|
||||||
purposes, a finer grain of (for example) 100 integers per Machi
|
|
||||||
chain would permit file migration to move increments of
|
|
||||||
approximately 1% of single Machi chain's storage capacity. A
|
|
||||||
minimum of 12+7=19 bits of hash space would be necessary to accommodate
|
|
||||||
these constraints.
|
|
||||||
|
|
||||||
It is likely that Machi's final implementation will choose a 24 bit
|
|
||||||
integer (or perhaps 32 bits) to represent the cluster locator.
|
|
||||||
|
|
||||||
* 7. Proposal: Break the opacity of Machi file names, slightly.
|
|
||||||
|
|
||||||
Machi assigns file names based on:
|
|
||||||
|
|
||||||
~ClientSuppliedPrefix ++ "^" ++ SomeOpaqueFileNameSuffix~
|
|
||||||
|
|
||||||
What if some parts of the system could peek inside of the opaque file name
|
|
||||||
suffix in order to look at the cluster location information that we might
|
|
||||||
code in the filename suffix?
|
|
||||||
|
|
||||||
We break the system into parts that speak two levels of protocols,
|
|
||||||
"high" and "low".
|
|
||||||
|
|
||||||
+ The high level protocol is used outside of the Machi cluster
|
|
||||||
+ The low level protocol is used inside of the Machi cluster
|
|
||||||
|
|
||||||
Both protocols are based on a Protocol Buffers specification and
|
|
||||||
implementation. Other protocols, such as HTTP, will be added later.
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
+-----------------------+
|
|
||||||
| Machi external client |
|
|
||||||
| e.g. Riak CS |
|
|
||||||
+-----------------------+
|
|
||||||
^
|
|
||||||
| Machi "high" API
|
|
||||||
| ProtoBuffs protocol Machi cluster boundary: outside
|
|
||||||
.........................................................................
|
|
||||||
| Machi cluster boundary: inside
|
|
||||||
v
|
|
||||||
+--------------------------+ +------------------------+
|
|
||||||
| Machi "high" API service | | Machi HTTP API service |
|
|
||||||
+--------------------------+ +------------------------+
|
|
||||||
^ |
|
|
||||||
| +------------------------+
|
|
||||||
v v
|
|
||||||
+------------------------+
|
|
||||||
| Cluster bridge service |
|
|
||||||
+------------------------+
|
|
||||||
^
|
|
||||||
| Machi "low" API
|
|
||||||
| ProtoBuffs protocol
|
|
||||||
+----------------------------------------+----+----+
|
|
||||||
| | | |
|
|
||||||
v v v v
|
|
||||||
+-------------------------+ ... other chains...
|
|
||||||
| Chain C1 (logical view) |
|
|
||||||
| +--------------+ |
|
|
||||||
| | FLU server 1 | |
|
|
||||||
| | +--------------+ |
|
|
||||||
| +--| FLU server 2 | |
|
|
||||||
| +--------------+ | In reality, API bridge talks directly
|
|
||||||
+-------------------------+ to each FLU server in a chain.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
** The notation we use
|
|
||||||
|
|
||||||
- ~N~ = the cluster namespace, chosen by the client.
|
|
||||||
- ~p~ = file prefix, chosen by the client.
|
|
||||||
- ~L~ = the cluster locator (a number, type is implementation-dependent)
|
|
||||||
- ~Map~ = a mapping of cluster locators to chains
|
|
||||||
- ~T~ = the target chain ID/name
|
|
||||||
- ~u~ = a unique opaque file name suffix, e.g. a GUID string
|
|
||||||
- ~F~ = a Machi file name, i.e., a concatenation of ~p^L^N^u~
|
|
||||||
|
|
||||||
** The details: cluster file append
|
|
||||||
|
|
||||||
0. Cluster client chooses ~N~ and ~p~ (i.e., cluster namespace and
|
|
||||||
file prefix) and sends the append request to a Machi cluster member
|
|
||||||
via the Protocol Buffers "high" API.
|
|
||||||
1. Cluster bridge chooses ~T~ (i.e., target chain), based on criteria
|
|
||||||
such as disk utilization percentage.
|
|
||||||
2. Cluster bridge knows the cluster ~Map~ for namespace ~N~.
|
|
||||||
3. Cluster bridge choose some cluster locator value ~L~ such that
|
|
||||||
~rs_hash_with_float(L,Map) = T~ (see algorithm below).
|
|
||||||
4. Cluster bridge sends its request to chain
|
|
||||||
~T~: ~append_chunk(p,L,N,...) -> {ok,p^L^N^u,ByteOffset}~
|
|
||||||
5. Cluster bridge forwards the reply tuple to the client.
|
|
||||||
6. Client stores/uses the file name ~F = p^L^N^u~.
|
|
||||||
|
|
||||||
** The details: Cluster file read
|
|
||||||
|
|
||||||
0. Cluster client sends the read request to a Machi cluster member via
|
|
||||||
the Protocol Buffers "high" API.
|
|
||||||
1. Cluster bridge parses the file name ~F~ to find
|
|
||||||
the values of ~L~ and ~N~ (recall, ~F = p^L^N^u~).
|
|
||||||
2. Cluster bridge knows the Cluster ~Map~ for type ~N~.
|
|
||||||
3. Cluster bridge calculates ~rs_hash_with_float(L,Map) = T~
|
|
||||||
4. Cluster bridge sends request to chain ~T~:
|
|
||||||
~read_chunk(F,...) ->~ ... reply
|
|
||||||
5. Cluster bridge forwards the reply to the client.
|
|
||||||
|
|
||||||
** The details: calculating 'L' (the cluster locator number) to match a desired target chain
|
|
||||||
|
|
||||||
1. We know ~Map~, the current cluster mapping for a cluster namespace ~N~.
|
|
||||||
2. We look inside of ~Map~, and we find all of the unit interval ranges
|
|
||||||
that map to our desired target chain ~T~. Let's call this list
|
|
||||||
~MapList = [Range1=(start,end],Range2=(start,end],...]~.
|
|
||||||
3. In our example, ~T=Chain2~. The example ~Map~ contains a single
|
|
||||||
unit interval range for ~Chain2~, ~[(0.33,0.58]]~.
|
|
||||||
4. Choose a uniformly random number ~r~ on the unit interval.
|
|
||||||
5. Calculate the cluster locator ~L~ by mapping ~r~ onto the concatenation
|
|
||||||
of the cluster hash space range intervals in ~MapList~. For example,
|
|
||||||
if ~r=0.5~, then ~L = 0.33 + 0.5*(0.58-0.33) = 0.455~, which is
|
|
||||||
exactly in the middle of the ~(0.33,0.58]~ interval.
|
|
||||||
|
|
||||||
** A bit more about the cluster namespaces's meaning and use
|
|
||||||
|
|
||||||
For use by Riak CS, for example, we'd likely start with the following
|
|
||||||
namespaces ... working our way down the list as we add new features
|
|
||||||
and/or re-implement existing CS features.
|
|
||||||
|
|
||||||
- "standard" = Chain length = 3, eventually consistency mode
|
|
||||||
- "reduced" = Chain length = 2, eventually consistency mode.
|
|
||||||
- "stanchion7" = Chain length = 7, strong consistency mode. Perhaps
|
|
||||||
use this namespace for the metadata required to re-implement the
|
|
||||||
operations that are performed by today's Stanchion application.
|
|
||||||
|
|
||||||
We want the cluster framework to:
|
|
||||||
|
|
||||||
- provide means of creating and managing
|
|
||||||
chains of different types, e.g., chain length, consistency mode.
|
|
||||||
- manage the mapping of cluster namespace
|
|
||||||
names to the chains in the system.
|
|
||||||
- provide query functions to map a cluster
|
|
||||||
namespace name to a cluster map,
|
|
||||||
e.g. ~get_cluster_latest_map("reduced") -> Map{generation=7,...}~.
|
|
||||||
|
|
||||||
* 8. File migration (a.k.a. rebalancing/reparitioning/resharding/redistribution)
|
|
||||||
|
|
||||||
** What is "migration"?
|
|
||||||
|
|
||||||
This section describes Machi's file migration. Other storage systems
|
|
||||||
call this process as "rebalancing", "repartitioning", "resharding" or
|
|
||||||
"redistribution".
|
|
||||||
For Riak Core applications, it is called "handoff" and "ring resizing"
|
|
||||||
(depending on the context).
|
|
||||||
See also the [[http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html#Balancer][Hadoop file balancer]] for another example of a data
|
|
||||||
migration process.
|
|
||||||
|
|
||||||
As discussed in section 5, the client can have good reason for wanting
|
|
||||||
to have some control of the initial location of the file within the
|
|
||||||
chain. However, the chain manager has an ongoing interest in
|
|
||||||
balancing resources throughout the lifetime of the file. Disks will
|
|
||||||
get full, hardware will change, read workload will fluctuate,
|
|
||||||
etc etc.
|
|
||||||
|
|
||||||
This document uses the word "migration" to describe moving data from
|
|
||||||
one Machi chain to another chain within a cluster system.
|
|
||||||
|
|
||||||
A simple variation of the Random Slicing hash algorithm can easily
|
|
||||||
accommodate Machi's need to migrate files without interfering with
|
|
||||||
availability. Machi's migration task is much simpler due to the
|
|
||||||
immutable nature of Machi file data.
|
|
||||||
|
|
||||||
** Change to Random Slicing
|
|
||||||
|
|
||||||
The map used by the Random Slicing hash algorithm needs a few simple
|
|
||||||
changes to make file migration straightforward.
|
|
||||||
|
|
||||||
- Add a "generation number", a strictly increasing number (similar to
|
|
||||||
a Machi chain's "epoch number") that reflects the history of
|
|
||||||
changes made to the Random Slicing map
|
|
||||||
- Use a list of Random Slicing maps instead of a single map, one map
|
|
||||||
per chance that files may not have been migrated yet out of
|
|
||||||
that map.
|
|
||||||
|
|
||||||
As an example:
|
|
||||||
|
|
||||||
#+CAPTION: Illustration of 'Map', using four Machi chains
|
|
||||||
|
|
||||||
[[./migration-3to4.png]]
|
|
||||||
|
|
||||||
And the new Random Slicing map for some cluster namespace ~N~ might look
|
|
||||||
like this:
|
|
||||||
|
|
||||||
| Generation number / Namespace | 7 / reduced |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| SubMap | 1 |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| Hash range | Chain ID |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| 0.00 - 0.33 | Chain1 |
|
|
||||||
| 0.33 - 0.66 | Chain2 |
|
|
||||||
| 0.66 - 1.00 | Chain3 |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| SubMap | 2 |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| Hash range | Chain ID |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| 0.00 - 0.25 | Chain1 |
|
|
||||||
| 0.25 - 0.33 | Chain4 |
|
|
||||||
| 0.33 - 0.58 | Chain2 |
|
|
||||||
| 0.58 - 0.66 | Chain4 |
|
|
||||||
| 0.66 - 0.91 | Chain3 |
|
|
||||||
| 0.91 - 1.00 | Chain4 |
|
|
||||||
|
|
||||||
When a new Random Slicing map contains a single submap, then its use
|
|
||||||
is identical to the original Random Slicing algorithm. If the map
|
|
||||||
contains multiple submaps, then the access rules change a bit:
|
|
||||||
|
|
||||||
- Write operations always go to the newest/largest submap.
|
|
||||||
- Read operations attempt to read from all unique submaps.
|
|
||||||
- Skip searching submaps that refer to the same chain ID.
|
|
||||||
- In this example, unit interval value 0.10 is mapped to Chain1
|
|
||||||
by both submaps.
|
|
||||||
- Read from newest/largest submap to oldest/smallest submap.
|
|
||||||
- If not found in any submap, search a second time (to handle races
|
|
||||||
with file copying between submaps).
|
|
||||||
- If the requested data is found, optionally copy it directly to the
|
|
||||||
newest submap. (This is a variation of read repair (RR). RR here
|
|
||||||
accelerates the migration process and can reduce the number of
|
|
||||||
operations required to query servers in multiple submaps).
|
|
||||||
|
|
||||||
The cluster manager is responsible for:
|
|
||||||
|
|
||||||
- Managing the various generations of the cluster Random Slicing maps for
|
|
||||||
all namespaces.
|
|
||||||
- Distributing namespace maps to cluster bridges.
|
|
||||||
- Managing the processes that are responsible for copying "cold" data,
|
|
||||||
i.e., files data that is not regularly accessed, to its new submap
|
|
||||||
location.
|
|
||||||
- When migration of a file to its new chain is confirmed successful,
|
|
||||||
delete it from the old chain.
|
|
||||||
|
|
||||||
In example map #7, the cluster manager will copy files with unit interval
|
|
||||||
assignments in ~(0.25,0.33]~, ~(0.58,0.66]~, and ~(0.91,1.00]~ from their
|
|
||||||
old locations in chain IDs Chain1/2/3 to their new chain,
|
|
||||||
Chain4. When the cluster manager is satisfied that all such files have
|
|
||||||
been copied to Chain4, then the cluster manager can create and
|
|
||||||
distribute a new map, such as:
|
|
||||||
|
|
||||||
| Generation number / Namespace | 8 / reduced |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| SubMap | 1 |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| Hash range | Chain ID |
|
|
||||||
|-------------------------------+-------------|
|
|
||||||
| 0.00 - 0.25 | Chain1 |
|
|
||||||
| 0.25 - 0.33 | Chain4 |
|
|
||||||
| 0.33 - 0.58 | Chain2 |
|
|
||||||
| 0.58 - 0.66 | Chain4 |
|
|
||||||
| 0.66 - 0.91 | Chain3 |
|
|
||||||
| 0.91 - 1.00 | Chain4 |
|
|
||||||
|
|
||||||
The HibariDB system performs data migrations in almost exactly this
|
|
||||||
manner. However, one important
|
|
||||||
limitation of HibariDB is not being able to
|
|
||||||
perform more than one migration at a time. HibariDB's data is
|
|
||||||
mutable. Mutation causes many problems when migrating data
|
|
||||||
across two submaps; three or more submaps was too complex to implement
|
|
||||||
quickly and correctly.
|
|
||||||
|
|
||||||
Fortunately for Machi, its file data is immutable and therefore can
|
|
||||||
easily manage many migrations in parallel, i.e., its submap list may
|
|
||||||
be several maps long, each one for an in-progress file migration.
|
|
||||||
|
|
||||||
* 9. Other considerations for FLU/sequencer implementations
|
|
||||||
|
|
||||||
** Append to existing file when possible
|
|
||||||
|
|
||||||
The sequencer should always assign new offsets to the latest/newest
|
|
||||||
file for any prefix, as long as all prerequisites are also true,
|
|
||||||
|
|
||||||
- The epoch has not changed. (In AP mode, epoch change -> mandatory
|
|
||||||
file name suffix change.)
|
|
||||||
- The cluster locator number is stable.
|
|
||||||
- The latest file for prefix ~p~ is smaller than maximum file size for
|
|
||||||
a FLU's configuration.
|
|
||||||
|
|
||||||
The stability of the cluster locator number is an implementation detail that
|
|
||||||
must be managed by the cluster bridge.
|
|
||||||
|
|
||||||
Reuse of the same file is not possible if the bridge always chooses a
|
|
||||||
different cluster locator number ~L~ or if the client always uses a unique
|
|
||||||
file prefix ~p~. The latter is a sign of a misbehaved client; the
|
|
||||||
former is a poorly-implemented bridge.
|
|
||||||
|
|
||||||
* 10. Acknowledgments
|
|
||||||
|
|
||||||
The original source for the "migration-4.png" and "migration-3to4.png" images
|
|
||||||
come from the [[http://hibari.github.io/hibari-doc/images/migration-3to4.png][HibariDB documentation]].
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
# Clone and compile Machi
|
|
||||||
|
|
||||||
Clone the Machi source repo and compile the source and test code. Run
|
|
||||||
the following commands at your login shell:
|
|
||||||
|
|
||||||
cd /tmp
|
|
||||||
git clone https://github.com/basho/machi.git
|
|
||||||
cd machi
|
|
||||||
git checkout master
|
|
||||||
make # or 'gmake' if GNU make uses an alternate name
|
|
||||||
|
|
||||||
Then run the unit test suite. This may take up to two minutes or so
|
|
||||||
to finish.
|
|
||||||
|
|
||||||
make test
|
|
||||||
|
|
||||||
At the end, the test suite should report that all tests passed. The
|
|
||||||
actual number of tests shown in the "All `X` tests passed" line may be
|
|
||||||
different than the example below.
|
|
||||||
|
|
||||||
[... many lines omitted ...]
|
|
||||||
module 'event_logger'
|
|
||||||
module 'chain_mgr_legacy'
|
|
||||||
=======================================================
|
|
||||||
All 90 tests passed.
|
|
||||||
|
|
||||||
If you had a test failure, a likely cause may be a limit on the number
|
|
||||||
of file descriptors available to your user process. (Recent releases
|
|
||||||
of OS X have a limit of 1024 file descriptors, which may be too slow.)
|
|
||||||
The output of the `limit -n` will tell you your file descriptor limit.
|
|
|
@ -1,38 +0,0 @@
|
||||||
## Machi developer environment prerequisites
|
|
||||||
|
|
||||||
1. Machi requires an 64-bit variant of UNIX: OS X, FreeBSD, Linux, or
|
|
||||||
Solaris machine is a standard developer environment for C and C++
|
|
||||||
applications (64-bit versions).
|
|
||||||
2. You'll need the `git` source management utility.
|
|
||||||
3. You'll need the 64-bit Erlang/OTP 17 runtime environment. Please
|
|
||||||
don't use earlier or later versions until we have a chance to fix
|
|
||||||
the compilation warnings that versions R16B and 18 will trigger.
|
|
||||||
Also, please verify that you are not using a 32-bit Erlang/OTP
|
|
||||||
runtime package.
|
|
||||||
|
|
||||||
For `git` and the Erlang runtime, please use your OS-specific
|
|
||||||
package manager to install these. If your package manager doesn't
|
|
||||||
have 64-bit Erlang/OTP version 17 available, then we recommend using the
|
|
||||||
[precompiled packages available at Erlang Solutions](https://www.erlang-solutions.com/resources/download.html).
|
|
||||||
|
|
||||||
Also, please verify that you have enough file descriptors available to
|
|
||||||
your user processes. The output of `ulimit -n` should report at least
|
|
||||||
4,000 file descriptors available. If your limit is lower (a frequent
|
|
||||||
problem for OS X users), please increase it to at least 4,000.
|
|
||||||
|
|
||||||
# Using Vagrant to set up a developer environment for Machi
|
|
||||||
|
|
||||||
The Machi source directory contains a `Vagrantfile` for creating an
|
|
||||||
Ubuntu Linux-based virtual machine for compiling and running Machi.
|
|
||||||
This file is in the
|
|
||||||
[$SRC_TOP/priv/humming-consensus-demo.vagrant](../priv/humming-consensus-demo.vagrant)
|
|
||||||
directory.
|
|
||||||
|
|
||||||
If used as-is, the virtual machine specification is modest.
|
|
||||||
|
|
||||||
* 1 virtual CPU
|
|
||||||
* 512MB virtual memory
|
|
||||||
* 768MB swap space
|
|
||||||
* 79GB sparse virtual disk image. After installing prerequisites and
|
|
||||||
compiling Machi, the root file system uses approximately 2.7 GBytes.
|
|
||||||
|
|
|
@ -1,617 +0,0 @@
|
||||||
FLU and Chain Life Cycle Management -*- mode: org; -*-
|
|
||||||
#+STARTUP: lognotedone hidestars indent showall inlineimages
|
|
||||||
#+COMMENT: To generate the outline section: egrep '^\*[*]* ' doc/flu-and-chain-lifecycle.org | egrep -v '^\* Outline' | sed -e 's/^\*\*\* / + /' -e 's/^\*\* / + /' -e 's/^\* /+ /'
|
|
||||||
|
|
||||||
* FLU and Chain Life Cycle Management
|
|
||||||
|
|
||||||
In an ideal world, we (the Machi development team) would have a full
|
|
||||||
vision of how Machi would be managed, down to the last detail of
|
|
||||||
beautiful CLI character and network protocol bit. Our vision isn't
|
|
||||||
complete yet, so we are working one small step at a time.
|
|
||||||
|
|
||||||
* Outline
|
|
||||||
|
|
||||||
+ FLU and Chain Life Cycle Management
|
|
||||||
+ Terminology review
|
|
||||||
+ Terminology: Machi run-time components/services/thingies
|
|
||||||
+ Terminology: Machi chain data structures
|
|
||||||
+ Terminology: Machi cluster data structures
|
|
||||||
+ Overview of administrative life cycles
|
|
||||||
+ Cluster administrative life cycle
|
|
||||||
+ Chain administrative life cycle
|
|
||||||
+ FLU server administrative life cycle
|
|
||||||
+ Quick admin: declarative management of Machi FLU and chain life cycles
|
|
||||||
+ Quick admin uses the "rc.d" config scheme for life cycle management
|
|
||||||
+ Quick admin's declarative "language": an Erlang-flavored AST
|
|
||||||
+ Term 'host': define a new host for FLU services
|
|
||||||
+ Term 'flu': define a new FLU
|
|
||||||
+ Term 'chain': define or reconfigure a chain
|
|
||||||
+ Executing quick admin AST files via the 'machi-admin' utility
|
|
||||||
+ Checking the syntax of an AST file
|
|
||||||
+ Executing an AST file
|
|
||||||
+ Using quick admin to manage multiple machines
|
|
||||||
+ The "rc.d" style configuration file scheme
|
|
||||||
+ Riak had a similar configuration file editing problem (and its solution)
|
|
||||||
+ Machi's "rc.d" file scheme.
|
|
||||||
+ FLU life cycle management using "rc.d" style files
|
|
||||||
+ The key configuration components of a FLU
|
|
||||||
+ Chain life cycle management using "rc.d" style files
|
|
||||||
+ The key configuration components of a chain
|
|
||||||
|
|
||||||
* Terminology review
|
|
||||||
|
|
||||||
** Terminology: Machi run-time components/services/thingies
|
|
||||||
|
|
||||||
+ FLU: a basic Machi server, responsible for managing a collection of
|
|
||||||
files.
|
|
||||||
|
|
||||||
+ Chain: a small collection of FLUs that maintain replicas of the same
|
|
||||||
collection of files. A chain is usually small, 1-3 servers, where
|
|
||||||
more than 3 would be used only in cases when availability of
|
|
||||||
certain data is critical despite failures of several machines.
|
|
||||||
+ The length of a chain is directly proportional to its
|
|
||||||
replication factor, e.g., a chain length=3 will maintain
|
|
||||||
(nominally) 3 replicas of each file.
|
|
||||||
+ To maintain file availability when ~F~ failures have occurred, a
|
|
||||||
chain must be at least ~F+1~ members long. (In comparison, the
|
|
||||||
quorum replication technique requires ~2F+1~ members in the
|
|
||||||
general case.)
|
|
||||||
|
|
||||||
+ Cluster: A collection of Machi chains that are used to store files
|
|
||||||
in a horizontally partitioned/sharded/distributed manner.
|
|
||||||
|
|
||||||
** Terminology: Machi data structures
|
|
||||||
|
|
||||||
+ Projection: used to define a single chain: the chain's consistency
|
|
||||||
mode (strong or eventual consistency), all members (from an
|
|
||||||
administrative point of view), all active members (from a runtime,
|
|
||||||
automatically-managed point of view), repairing/file-syncing members
|
|
||||||
(also runtime, auto-managed), and so on
|
|
||||||
|
|
||||||
+ Epoch: A version number of a projection. The epoch number is used
|
|
||||||
by both clients & servers to manage transitions from one projection
|
|
||||||
to another, e.g., when the chain is temporarily shortened by the
|
|
||||||
failure of a member FLU server.
|
|
||||||
|
|
||||||
** Terminology: Machi cluster data structures
|
|
||||||
|
|
||||||
+ Namespace: A collection of human-friendly names that are mapped to
|
|
||||||
groups of Machi chains that provide the same type of storage
|
|
||||||
service: consistency mode, replication policy, etc.
|
|
||||||
+ A single namespace name, e.g. ~normal-ec~, is paired with a single
|
|
||||||
cluster map (see below).
|
|
||||||
+ Example: ~normal-ec~ might be a collection of Machi chains in
|
|
||||||
eventually-consistent mode that are of length=3.
|
|
||||||
+ Example: ~risky-ec~ might be a collection of Machi chains in
|
|
||||||
eventually-consistent mode that are of length=1.
|
|
||||||
+ Example: ~mgmt-critical~ might be a collection of Machi chains in
|
|
||||||
strongly-consistent mode that are of length=7.
|
|
||||||
|
|
||||||
+ Cluster map: Encodes the rules which partition/shard/distribute
|
|
||||||
the files stored in a particular namespace across a group of chains
|
|
||||||
that collectively store the namespace's files.
|
|
||||||
|
|
||||||
+ Chain weight: A value assigned to each chain within a cluster map
|
|
||||||
structure that defines the relative storage capacity of a chain
|
|
||||||
within the namespace. For example, a chain weight=150 has 50% more
|
|
||||||
capacity than a chain weight=100.
|
|
||||||
|
|
||||||
+ Cluster map epoch: The version number assigned to a cluster map.
|
|
||||||
|
|
||||||
* Overview of administrative life cycles
|
|
||||||
|
|
||||||
** Cluster administrative life cycle
|
|
||||||
|
|
||||||
+ Cluster is first created
|
|
||||||
+ Adds namespaces (e.g. consistency policy + chain length policy) to
|
|
||||||
the cluster
|
|
||||||
+ Chains are added to/removed from a namespace to increase/decrease the
|
|
||||||
namespace's storage capacity.
|
|
||||||
+ Adjust chain weights within a namespace, e.g., to shift files
|
|
||||||
within the namespace to chains with greater storage capacity
|
|
||||||
resources and/or runtime I/O resources.
|
|
||||||
|
|
||||||
A cluster "file migration" is the process of moving files from one
|
|
||||||
namespace member chain to another for purposes of shifting &
|
|
||||||
re-balancing storage capacity and/or runtime I/O capacity.
|
|
||||||
|
|
||||||
** Chain administrative life cycle
|
|
||||||
|
|
||||||
+ A chain is created with an initial FLU membership list.
|
|
||||||
+ Chain may be administratively modified zero or more times to
|
|
||||||
add/remove member FLU servers.
|
|
||||||
+ A chain may be decommissioned.
|
|
||||||
|
|
||||||
See also: http://basho.github.io/machi/edoc/machi_lifecycle_mgr.html
|
|
||||||
|
|
||||||
** FLU server administrative life cycle
|
|
||||||
|
|
||||||
+ A FLU is created after an administrator chooses the FLU's runtime
|
|
||||||
location is selected by the administrator: which machine/virtual
|
|
||||||
machine, IP address and TCP port allocation, etc.
|
|
||||||
+ An unassigned FLU may be added to a chain by chain administrative
|
|
||||||
policy.
|
|
||||||
+ A FLU that is assigned to a chain may be removed from that chain by
|
|
||||||
chain administrative policy.
|
|
||||||
+ In the current implementation, the FLU's Erlang processes will be
|
|
||||||
halted. Then the FLU's data and metadata files will be moved to
|
|
||||||
another area of the disk for safekeeping. Later, a "garbage
|
|
||||||
collection" process can be used for reclaiming disk space used by
|
|
||||||
halted FLU servers.
|
|
||||||
|
|
||||||
See also: http://basho.github.io/machi/edoc/machi_lifecycle_mgr.html
|
|
||||||
|
|
||||||
* Quick admin: declarative management of Machi FLU and chain life cycles
|
|
||||||
|
|
||||||
The "quick admin" scheme is a temporary (?) tool for managing Machi
|
|
||||||
FLU server and chain life cycles in a declarative manner. The API is
|
|
||||||
described in this section.
|
|
||||||
|
|
||||||
** Quick admin uses the "rc.d" config scheme for life cycle management
|
|
||||||
|
|
||||||
As described at the top of
|
|
||||||
http://basho.github.io/machi/edoc/machi_lifecycle_mgr.html, the "rc.d"
|
|
||||||
config files do not manage "policy". "Policy" is doing the right
|
|
||||||
thing with a Machi cluster from a systems administrator's
|
|
||||||
point of view. The "rc.d" config files can only implement decisions
|
|
||||||
made according to policy.
|
|
||||||
|
|
||||||
The "quick admin" tool is a first attempt at automating policy
|
|
||||||
decisions in a safe way (we hope) that is also easy to implement (we
|
|
||||||
hope) with a variety of systems management tools, e.g. Chef, Puppet,
|
|
||||||
Ansible, Saltstack, or plain-old-human-at-a-keyboard.
|
|
||||||
|
|
||||||
** Quick admin's declarative "language": an Erlang-flavored AST
|
|
||||||
|
|
||||||
The "language" that an administrator uses to express desired policy
|
|
||||||
changes is not (yet) a true language. As a quick implementation hack,
|
|
||||||
the current language is an Erlang-flavored abstract syntax tree
|
|
||||||
(AST). The tree isn't very deep, either, frequently just one
|
|
||||||
element tall. (Not much of a tree, is it?)
|
|
||||||
|
|
||||||
There are three terms in the language currently:
|
|
||||||
|
|
||||||
+ ~host~, define a new host that can execute FLU servers
|
|
||||||
+ ~flu~, define a new FLU
|
|
||||||
+ ~chain~, define a new chain or re-configure an existing chain with
|
|
||||||
the same name
|
|
||||||
|
|
||||||
*** Term 'host': define a new host for FLU services
|
|
||||||
|
|
||||||
In this context, a host is a machine, virtual machine, or container
|
|
||||||
that can execute the Machi application and can therefore provide FLU
|
|
||||||
services, i.e. file service, Humming Consensus management.
|
|
||||||
|
|
||||||
Two formats may be used to define a new host:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{host, Name, Props}.
|
|
||||||
{host, Name, AdminI, ClientI, Props}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
The shorter tuple is shorthand notation for the latter. If the
|
|
||||||
shorthand form is used, then it will be converted automatically to the
|
|
||||||
long form as:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{host, Name, AdminI=Name, ClientI=Name, Props}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
Type information, description, and restrictions:
|
|
||||||
|
|
||||||
+ ~Name::string()~ The ~Name~ attribute must be unique. Note that it
|
|
||||||
is possible to define two different hosts, one using a DNS hostname
|
|
||||||
and one using an IP address. The user must avoid this
|
|
||||||
double-definition because it is not enforced by quick admin.
|
|
||||||
+ The ~Name~ field is used for cross-reference purposes with other
|
|
||||||
terms, e.g., ~flu~ and ~chain~.
|
|
||||||
+ There is no syntax yet for removing a host definition.
|
|
||||||
|
|
||||||
+ ~AdminI::string()~ A DNS hostname or IP address for cluster
|
|
||||||
administration purposes, e.g. SSH access.
|
|
||||||
+ This field is unused at the present time.
|
|
||||||
|
|
||||||
+ ~ClientI::string()~ A DNS hostname or IP address for Machi's client
|
|
||||||
protocol access, e.g., Protocol Buffers network API service.
|
|
||||||
+ This field is unused at the present time.
|
|
||||||
|
|
||||||
+ ~props::proplist()~ is an Erlang-style property list for specifying
|
|
||||||
additional configuration options, debugging information, sysadmin
|
|
||||||
comments, etc.
|
|
||||||
|
|
||||||
+ A full-featured admin tool should also include managing several
|
|
||||||
other aspects of configuration related to a "host". For example,
|
|
||||||
for any single IP address, quick admin assumes that there will be
|
|
||||||
exactly one Erlang VM that is running the Machi application. Of
|
|
||||||
course, it is possible to have dozens of Erlang VMs on the same
|
|
||||||
(let's assume for clarity) hardware machine and all running Machi
|
|
||||||
... but there are additional aspects of such a machine that quick
|
|
||||||
admin does not account for
|
|
||||||
+ multiple IP addresses per machine
|
|
||||||
+ multiple Machi package installation paths
|
|
||||||
+ multiple Machi config files (e.g. cuttlefish config, ~etc.conf~,
|
|
||||||
~vm.args~)
|
|
||||||
+ multiple data directories/file system mount points
|
|
||||||
+ This is also a management problem for quick admin for a single
|
|
||||||
Machi package on a machine to take advantage of bulk data
|
|
||||||
storage using multiple multiple file system mount points.
|
|
||||||
+ multiple Erlang VM host names, required for distributed Erlang,
|
|
||||||
which is used for communication with ~machi~ and ~machi-admin~
|
|
||||||
command line utilities.
|
|
||||||
+ and others....
|
|
||||||
|
|
||||||
*** Term 'flu': define a new FLU
|
|
||||||
|
|
||||||
A new FLU is defined relative to a previously-defined ~host~ entities;
|
|
||||||
an exception will be thrown if the ~host~ cannot be cross-referenced.
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{flu, Name, HostName, Port, Props}
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
Type information, description, and restrictions:
|
|
||||||
|
|
||||||
+ ~Name::atom()~ The name of the FLU, as a human-friendly name and
|
|
||||||
also for internal management use; please note the ~atom()~ type.
|
|
||||||
This name must be unique.
|
|
||||||
+ The ~Name~ field is used for cross-reference purposes with the
|
|
||||||
~chain~ term.
|
|
||||||
+ There is no syntax yet for removing a FLU definition.
|
|
||||||
|
|
||||||
+ ~Hostname::string()~ The cross-reference name of the ~host~ that
|
|
||||||
this FLU should run on.
|
|
||||||
|
|
||||||
+ ~Port::non_neg_integer()~ The TCP port used by this FLU server's
|
|
||||||
Protocol Buffers network API listener service
|
|
||||||
|
|
||||||
+ ~props::proplist()~ is an Erlang-style property list for specifying
|
|
||||||
additional configuration options, debugging information, sysadmin
|
|
||||||
comments, etc.
|
|
||||||
|
|
||||||
*** Term 'chain': define or reconfigure a chain
|
|
||||||
|
|
||||||
A chain is defined relative to zero or more previously-defined ~flu~
|
|
||||||
entities; an exception will be thrown if any ~flu~ cannot be
|
|
||||||
cross-referenced.
|
|
||||||
|
|
||||||
Two formats may be used to define/reconfigure a chain:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{chain, Name, FullList, Props}.
|
|
||||||
{chain, Name, CMode, FullList, Witnesses, Props}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
The shorter tuple is shorthand notation for the latter. If the
|
|
||||||
shorthand form is used, then it will be converted automatically to the
|
|
||||||
long form as:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{chain, Name, ap_mode, FullList, [], Props}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
Type information, description, and restrictions:
|
|
||||||
|
|
||||||
+ ~Name::atom()~ The name of the chain, as a human-friendly name and
|
|
||||||
also for internal management use; please note the ~atom()~ type.
|
|
||||||
This name must be unique.
|
|
||||||
+ There is no syntax yet for removing a chain definition.
|
|
||||||
|
|
||||||
+ ~CMode::'ap_mode'|'cp_mode'~ Defines the consistency mode of the
|
|
||||||
chain, either eventual consistency or strong consistency,
|
|
||||||
respectively.
|
|
||||||
+ A chain cannot change consistency mode, e.g., from
|
|
||||||
strong~->~eventual consistency.
|
|
||||||
|
|
||||||
+ ~FullList::list(atom())~ Specifies the list of full-service FLU
|
|
||||||
servers, i.e. servers that provide file data & metadata services as
|
|
||||||
well as Humming Consensus. Each atom in the list must
|
|
||||||
cross-reference with a previously defined ~chain~; an exception will
|
|
||||||
be thrown if any ~flu~ cannot be cross-referenced.
|
|
||||||
|
|
||||||
+ ~Witnesses::list(atom())~ Specifies the list of witness-only
|
|
||||||
servers, i.e. servers that only participate in Humming Consensus.
|
|
||||||
Each atom in the list must cross-reference with a previously defined
|
|
||||||
~chain~; an exception will be thrown if any ~flu~ cannot be
|
|
||||||
cross-referenced.
|
|
||||||
+ This list must be empty for eventual consistency chains.
|
|
||||||
|
|
||||||
+ ~props::proplist()~ is an Erlang-style property list for specifying
|
|
||||||
additional configuration options, debugging information, sysadmin
|
|
||||||
comments, etc.
|
|
||||||
|
|
||||||
+ If this term specifies a new ~chain~ name, then all of the member
|
|
||||||
FLU servers (full & witness types) will be bootstrapped to a
|
|
||||||
starting configuration.
|
|
||||||
|
|
||||||
+ If this term specifies a previously-defined ~chain~ name, then all
|
|
||||||
of the member FLU servers (full & witness types, respectively) will
|
|
||||||
be adjusted to add or remove members, as appropriate.
|
|
||||||
+ Any FLU servers added to either list must not be assigned to any
|
|
||||||
other chain, or they must be a member of this specific chain.
|
|
||||||
+ Any FLU servers removed from either list will be halted.
|
|
||||||
(See the "FLU server administrative life cycle" section above.)
|
|
||||||
|
|
||||||
** Executing quick admin AST files via the 'machi-admin' utility
|
|
||||||
|
|
||||||
Examples of quick admin AST files can be found in the
|
|
||||||
~priv/quick-admin/examples~ directory. Below is an example that will
|
|
||||||
define a new host ( ~"localhost"~ ), three new FLU servers ( ~f1~ & ~f2~
|
|
||||||
and ~f3~ ), and an eventually consistent chain ( ~c1~ ) that uses the new
|
|
||||||
FLU servers:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{host, "localhost", []}.
|
|
||||||
{flu,f1,"localhost",20401,[]}.
|
|
||||||
{flu,f2,"localhost",20402,[]}.
|
|
||||||
{flu,f3,"localhost",20403,[]}.
|
|
||||||
{chain,c1,[f1,f2,f3],[]}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
*** Checking the syntax of an AST file
|
|
||||||
|
|
||||||
Given an AST config file, ~/path/to/ast/file~, its basic syntax and
|
|
||||||
correctness can be checked without executing it.
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
./rel/machi/bin/machi-admin quick-admin-check /path/to/ast/file
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
+ The utility will exit with status zero and output ~ok~ if the syntax
|
|
||||||
and proposed configuration appears to be correct.
|
|
||||||
+ If there is an error, the utility will exit with status one, and an
|
|
||||||
error message will be printed.
|
|
||||||
|
|
||||||
*** Executing an AST file
|
|
||||||
|
|
||||||
Given an AST config file, ~/path/to/ast/file~, it can be executed
|
|
||||||
using the command:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
./rel/machi/bin/machi-admin quick-admin-apply /path/to/ast/file RelativeHost
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
... where the last argument, ~RelativeHost~, should be the exact
|
|
||||||
spelling of one of the previously defined AST ~host~ entities,
|
|
||||||
*and also* is the same host that the ~machi-admin~ utility is being
|
|
||||||
executed on.
|
|
||||||
|
|
||||||
Restrictions and warnings:
|
|
||||||
|
|
||||||
+ This is alpha quality software.
|
|
||||||
|
|
||||||
+ There is no "undo".
|
|
||||||
+ Of course there is, but you need to resort to doing things like
|
|
||||||
using ~machi attach~ to attach to the server's CLI to then execute
|
|
||||||
magic Erlang incantations to stop FLUs, unconfigure chains, etc.
|
|
||||||
+ Oh, and delete some files with magic paths, also.
|
|
||||||
|
|
||||||
** Using quick admin to manage multiple machines
|
|
||||||
|
|
||||||
A quick sketch follows:
|
|
||||||
|
|
||||||
1. Create the AST file to specify all of the changes that you wish to
|
|
||||||
make to all hosts, FLUs, and/or chains, e.g., ~/tmp/ast.txt~.
|
|
||||||
2. Check the basic syntax with the ~quick-admin-check~ argument to
|
|
||||||
~machi-admin~.
|
|
||||||
3. If the syntax is good, then copy ~/tmp/ast.txt~ to all hosts in the
|
|
||||||
cluster, using the same path, ~/tmp/ast.txt~.
|
|
||||||
4. For each machine in the cluster, run:
|
|
||||||
#+BEGIN_SRC
|
|
||||||
./rel/machi/bin/machi-admin quick-admin-apply /tmp/ast.txt RelativeHost
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
... where RelativeHost is the AST ~host~ name of the machine that you
|
|
||||||
are executing the ~machi-admin~ command on. The command should be
|
|
||||||
successful, with exit status 0 and outputting the string ~ok~.
|
|
||||||
|
|
||||||
Finally, for each machine in the cluster, a listing of all files in
|
|
||||||
the directory ~rel/machi/etc/quick-admin-archive~ should show exactly
|
|
||||||
the same files, one for each time that ~quick-admin-apply~ has been
|
|
||||||
run successfully on that machine.
|
|
||||||
|
|
||||||
* The "rc.d" style configuration file scheme
|
|
||||||
|
|
||||||
This configuration scheme is inspired by BSD UNIX's ~init(8)~ process
|
|
||||||
manager's configuration style, called "rc.d" after the name of the
|
|
||||||
directory where these files are stored, ~/etc/rc.d~. The ~init~
|
|
||||||
process is responsible for (among other things) starting UNIX
|
|
||||||
processes at machine boot time and stopping them when the machine is
|
|
||||||
shut down.
|
|
||||||
|
|
||||||
The original scheme used by ~init~ to start processes at boot time was
|
|
||||||
a single Bourne shell script called ~/etc/rc~. When a new software
|
|
||||||
package was installed that required a daemon to be started at boot
|
|
||||||
time, text was added to the ~/etc/rc~ file. Uninstalling packages was
|
|
||||||
much trickier, because it meant removing lines from a file that
|
|
||||||
*is a computer program (run by the Bourne shell, a Turing-complete
|
|
||||||
programming language)*. Error-free editing of the ~/etc/rc~ script
|
|
||||||
was impossible in all cases.
|
|
||||||
|
|
||||||
Later, ~init~'s configuration was split into a few master Bourne shell
|
|
||||||
scripts and a subdirectory, ~/etc/rc.d~. The subdirectory contained
|
|
||||||
shell scripts that were responsible for boot time starting of a single
|
|
||||||
daemon or service, e.g. NFS or an HTTP server. When a new software
|
|
||||||
package was added, a new file was added to the ~rc.d~ subdirectory.
|
|
||||||
When a package was removed, the corresponding file in ~rc.d~ was
|
|
||||||
removed. With this simple scheme, addition & removal of boot time
|
|
||||||
scripts was vastly simplified.
|
|
||||||
|
|
||||||
** Riak had a similar configuration file editing problem (and its solution)
|
|
||||||
|
|
||||||
Another software product from Basho Technologies, Riak, had a similar
|
|
||||||
configuration file editing problem. One file in particular,
|
|
||||||
~app.config~, had a syntax that made it difficult both for human
|
|
||||||
systems administrators and also computer programs to edit the file in
|
|
||||||
a syntactically correct manner.
|
|
||||||
|
|
||||||
Later releases of Riak switched to an alternative configuration file
|
|
||||||
format, one inspired by the BSD UNIX ~sysctl(8)~ utility and
|
|
||||||
~sysctl.conf(5)~ file syntax. The ~sysctl.conf~ format is much easier
|
|
||||||
to manage by computer programs to add items. Removing items is not
|
|
||||||
100% simple, however: the correct lines must be identified and then
|
|
||||||
removed (e.g. with Perl or a text editor or combination of ~grep -v~
|
|
||||||
and ~mv~), but removing any comment lines that "belong" to the removed
|
|
||||||
config item(s) is not any easy for a 1-line shell script to do 100%
|
|
||||||
correctly.
|
|
||||||
|
|
||||||
Machi will use the ~sysctl.conf~ style configuration for some
|
|
||||||
application configuration variables. However, adding & removing FLUs
|
|
||||||
and chains will be managed using the "rc.d" style because of the
|
|
||||||
"rc.d" scheme's simplicity and tolerance of mistakes by administrators
|
|
||||||
(human or computer).
|
|
||||||
|
|
||||||
** Machi's "rc.d" file scheme.
|
|
||||||
|
|
||||||
Machi will use a single subdirectory that will contain configuration
|
|
||||||
files for some life cycle management task, e.g. a single FLU or a
|
|
||||||
single chain.
|
|
||||||
|
|
||||||
The contents of the file should be a single Erlang term, serialized in
|
|
||||||
ASCII form as Erlang source code statement, i.e. a single Erlang term
|
|
||||||
~T~ that is formatted by ~io:format("~w.",[T]).~. This file must be
|
|
||||||
parseable by the Erlang function ~file:consult()~.
|
|
||||||
|
|
||||||
Later versions of Machi may change the file format to be more familiar
|
|
||||||
to administrators who are unaccustomed to Erlang language syntax.
|
|
||||||
|
|
||||||
** FLU life cycle management using "rc.d" style files
|
|
||||||
|
|
||||||
*** The key configuration components of a FLU
|
|
||||||
|
|
||||||
1. The machine (or virtual machine) to run it on.
|
|
||||||
2. The Machi software package's artifacts to execute.
|
|
||||||
3. The disk device(s) used to store Machi file data & metadata, "rc.d"
|
|
||||||
style config files, etc.
|
|
||||||
4. The name, IP address and TCP port assigned to the FLU service.
|
|
||||||
5. Its chain assignment.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
+ Items 1-3 are currently outside of the scope of this life cycle
|
|
||||||
document. We assume that human administrators know how to do these
|
|
||||||
things.
|
|
||||||
+ Item 4's properties are explicitly managed by a FLU-defining "rc.d"
|
|
||||||
style config file.
|
|
||||||
+ Item 5 is managed by the chain life cycle management system.
|
|
||||||
|
|
||||||
Here is an example of a properly formatted FLU config file:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{p_srvr,f1,machi_flu1_client,"192.168.72.23",20401,[]}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
... which corresponds to the following Erlang record definition:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
-record(p_srvr, {
|
|
||||||
name :: atom(),
|
|
||||||
proto_mod = 'machi_flu1_client' :: atom(), % Module name
|
|
||||||
address :: term(), % Protocol-specific
|
|
||||||
port :: term(), % Protocol-specific
|
|
||||||
props = [] :: list() % proplist for other related info
|
|
||||||
}).
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
+ ~name~ is ~f1~. This is name of the FLU. This name should be
|
|
||||||
unique over the lifetime of the administrative domain and thus
|
|
||||||
managed by external policy. This name must be the same as the name
|
|
||||||
of the config file that defines the FLU.
|
|
||||||
+ ~proto_mod~ is used for internal management purposes and should be
|
|
||||||
considered a mandatory constant.
|
|
||||||
+ ~address~ is "192.168.72.23". The DNS hostname or IP address used
|
|
||||||
by other servers to communicate with this FLU. This must be a valid
|
|
||||||
IP address, previously assigned to this machine/VM using the
|
|
||||||
appropriate operating system-specific procedure.
|
|
||||||
+ ~port~ is TCP port 20401. The TCP port number that the FLU listens
|
|
||||||
to for incoming Protocol Buffers-serialized communication. This TCP
|
|
||||||
port must not be in use (now or in the future) by another Machi FLU
|
|
||||||
or any other process running on this machine/VM.
|
|
||||||
+ ~props~ is an Erlang-style property list for specifying additional
|
|
||||||
configuration options, debugging information, sysadmin comments,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
** Chain life cycle management using "rc.d" style files
|
|
||||||
|
|
||||||
Unlike FLUs, chains have a self-management aspect that makes a chain
|
|
||||||
life cycle different from a single FLU server. Machi's chains are
|
|
||||||
self-managing, via Humming Consensus; see the
|
|
||||||
https://github.com/basho/machi/tree/master/doc/ directory for much
|
|
||||||
more detail about Humming Consensus. After FLUs have received their
|
|
||||||
initial chain configuration for Humming Consensus, the FLUs will
|
|
||||||
manage the chain (and each other) by themselves.
|
|
||||||
|
|
||||||
However, Humming Consensus does not handle three chain management
|
|
||||||
problems:
|
|
||||||
|
|
||||||
1. Specifying the very first chain configuration,
|
|
||||||
2. Altering the membership of the chain (i.e. adding/removing FLUs
|
|
||||||
from the chain),
|
|
||||||
3. Stopping the chain permanently.
|
|
||||||
|
|
||||||
A chain "rc.d" file will only be used to bootstrap a newly-defined FLU
|
|
||||||
server. It's like a piece of glue information to introduce the new
|
|
||||||
FLU to the Humming Consensus group that is managing the chain's
|
|
||||||
dynamic state (e.g. which members are up or down). In all other
|
|
||||||
respects, chain config files are ignored by life cycle management code.
|
|
||||||
However, to mimic the life cycle of the FLU server's "rc.d" config
|
|
||||||
files, a chain "rc.d" files is not deleted until the chain has been
|
|
||||||
decommissioned (i.e. defined with length=0).
|
|
||||||
|
|
||||||
*** The key configuration components of a chain
|
|
||||||
|
|
||||||
1. The name of the chain.
|
|
||||||
2. Consistency mode: eventually consistent or strongly consistent.
|
|
||||||
3. The membership list of all FLU servers in the chain.
|
|
||||||
+ Remember, all servers in a single chain will manage full replicas
|
|
||||||
of the same collection of Machi files.
|
|
||||||
4. If the chain is defined to use strongly consistent mode, then a
|
|
||||||
list of "witness servers" may also be defined. See the
|
|
||||||
[https://github.com/basho/machi/tree/master/doc/] documentation for
|
|
||||||
more information on witness servers.
|
|
||||||
+ The witness list must be empty for all chains in eventual
|
|
||||||
consistency mode.
|
|
||||||
|
|
||||||
Here is an example of a properly formatted chain config file:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
{chain_def_v1,c1,ap_mode,
|
|
||||||
[{p_srvr,f1,machi_flu1_client,"localhost",20401,[]},
|
|
||||||
{p_srvr,f2,machi_flu1_client,"localhost",20402,[]},
|
|
||||||
{p_srvr,f3,machi_flu1_client,"localhost",20403,[]}],
|
|
||||||
[],[],[],
|
|
||||||
[f1,f2,f3],
|
|
||||||
[],[]}.
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
... which corresponds to the following Erlang record definition:
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
-record(chain_def_v1, {
|
|
||||||
name :: atom(), % chain name
|
|
||||||
mode :: 'ap_mode' | 'cp_mode',
|
|
||||||
full = [] :: [p_srvr()],
|
|
||||||
witnesses = [] :: [p_srvr()],
|
|
||||||
old_full = [] :: [atom()], % guard against some races
|
|
||||||
old_witnesses=[] :: [atom()], % guard against some races
|
|
||||||
local_run = [] :: [atom()], % must be tailored to each machine!
|
|
||||||
local_stop = [] :: [atom()], % must be tailored to each machine!
|
|
||||||
props = [] :: list() % proplist for other related info
|
|
||||||
}).
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
+ ~name~ is ~c1~, the name of the chain. This name should be unique
|
|
||||||
over the lifetime of the administrative domain and thus managed by
|
|
||||||
external policy. This name must be the same as the name of the
|
|
||||||
config file that defines the chain.
|
|
||||||
+ ~mode~ is ~ap_mode~, an internal code symbol for eventual
|
|
||||||
consistency mode.
|
|
||||||
+ ~full~ is a list of Erlang ~#p_srvr{}~ records for full-service
|
|
||||||
members of the chain, i.e., providing Machi file data & metadata
|
|
||||||
storage services.
|
|
||||||
+ ~witnesses~ is a list of Erlang ~#p_srvr{}~ records for witness-only
|
|
||||||
FLU servers, i.e., providing only Humming Consensus service.
|
|
||||||
+ The next four fields are used for internal management only.
|
|
||||||
+ ~props~ is an Erlang-style property list for specifying additional
|
|
||||||
configuration options, debugging information, sysadmin comments,
|
|
||||||
etc.
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,372 +0,0 @@
|
||||||
|
|
||||||
# Table of contents
|
|
||||||
|
|
||||||
* [Hands-on experiments with Machi and Humming Consensus](#hands-on)
|
|
||||||
* [Using the network partition simulator and convergence demo test code](#partition-simulator)
|
|
||||||
|
|
||||||
<a name="hands-on">
|
|
||||||
# Hands-on experiments with Machi and Humming Consensus
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Please refer to the
|
|
||||||
[Machi development environment prerequisites doc](./dev-prerequisites.md)
|
|
||||||
for Machi developer environment prerequisites.
|
|
||||||
|
|
||||||
If you do not have an Erlang/OTP runtime system available, but you do
|
|
||||||
have [the Vagrant virtual machine](https://www.vagrantup.com/) manager
|
|
||||||
available, then please refer to the instructions in the prerequisites
|
|
||||||
doc for using Vagrant.
|
|
||||||
|
|
||||||
<a name="clone-compile">
|
|
||||||
## Clone and compile the code
|
|
||||||
|
|
||||||
Please see the
|
|
||||||
[Machi 'clone and compile' doc](./dev-clone-compile.md)
|
|
||||||
for the short list of steps required to fetch the Machi source code
|
|
||||||
from GitHub and to compile & test Machi.
|
|
||||||
|
|
||||||
## Running three Machi instances on a single machine
|
|
||||||
|
|
||||||
All of the commands that should be run at your login shell (e.g. Bash,
|
|
||||||
c-shell) can be cut-and-pasted from this document directly to your
|
|
||||||
login shell prompt.
|
|
||||||
|
|
||||||
Run the following command:
|
|
||||||
|
|
||||||
make stagedevrel
|
|
||||||
|
|
||||||
This will create a directory structure like this:
|
|
||||||
|
|
||||||
|-dev1-|... stand-alone Machi app + subdirectories
|
|
||||||
|-dev-|-dev2-|... stand-alone Machi app + directories
|
|
||||||
|-dev3-|... stand-alone Machi app + directories
|
|
||||||
|
|
||||||
Each of the `dev/dev1`, `dev/dev2`, and `dev/dev3` are stand-alone
|
|
||||||
application instances of Machi and can be run independently of each
|
|
||||||
other on the same machine. This demo will use all three.
|
|
||||||
|
|
||||||
The lifecycle management utilities for Machi are a bit immature,
|
|
||||||
currently. They assume that each Machi server runs on a host with a
|
|
||||||
unique hostname -- there is no flexibility built-in yet to easily run
|
|
||||||
multiple Machi instances on the same machine. To continue with the
|
|
||||||
demo, we need to use `sudo` or `su` to obtain superuser privileges to
|
|
||||||
edit the `/etc/hosts` file.
|
|
||||||
|
|
||||||
Please add the following line to `/etc/hosts`, using this command:
|
|
||||||
|
|
||||||
sudo sh -c 'echo "127.0.0.1 machi1 machi2 machi3" >> /etc/hosts'
|
|
||||||
|
|
||||||
Next, we will use a shell script to finish setting up our cluster. It
|
|
||||||
will do the following for us:
|
|
||||||
|
|
||||||
* Verify that the new line that was added to `/etc/hosts` is correct.
|
|
||||||
* Modify the `etc/app.config` files to configure the Humming Consensus
|
|
||||||
chain manager's actions logged to the `log/console.log` file.
|
|
||||||
* Start the three application instances.
|
|
||||||
* Verify that the three instances are running correctly.
|
|
||||||
* Configure a single chain, with one FLU server per application
|
|
||||||
instance.
|
|
||||||
|
|
||||||
Please run this script using this command:
|
|
||||||
|
|
||||||
./priv/humming-consensus-demo.setup.sh
|
|
||||||
|
|
||||||
If the output looks like this (and exits with status zero), then the
|
|
||||||
script was successful.
|
|
||||||
|
|
||||||
Step: Verify that the required entries in /etc/hosts are present
|
|
||||||
Step: add a verbose logging option to app.config
|
|
||||||
Step: start three three Machi application instances
|
|
||||||
pong
|
|
||||||
pong
|
|
||||||
pong
|
|
||||||
Step: configure one chain to start a Humming Consensus group with three members
|
|
||||||
Result: ok
|
|
||||||
Result: ok
|
|
||||||
Result: ok
|
|
||||||
|
|
||||||
We have now created a single replica chain, called `c1`, that has
|
|
||||||
three file servers participating in the chain. Thanks to the
|
|
||||||
hostnames that we added to `/etc/hosts`, all are using the localhost
|
|
||||||
network interface.
|
|
||||||
|
|
||||||
| App instance | Pseudo | FLU name | TCP port |
|
|
||||||
| directory | Hostname | | number |
|
|
||||||
|--------------+----------+----------+----------|
|
|
||||||
| dev1 | machi1 | flu1 | 20401 |
|
|
||||||
| dev2 | machi2 | flu2 | 20402 |
|
|
||||||
| dev3 | machi3 | flu3 | 20403 |
|
|
||||||
|
|
||||||
The log files for each application instance can be found in the
|
|
||||||
`./dev/devN/log/console.log` file, where the `N` is the instance
|
|
||||||
number: 1, 2, or 3.
|
|
||||||
|
|
||||||
## Understanding the chain manager's log file output
|
|
||||||
|
|
||||||
After running the `./priv/humming-consensus-demo.setup.sh` script,
|
|
||||||
let's look at the last few lines of the `./dev/dev1/log/console.log`
|
|
||||||
log file for Erlang VM process #1.
|
|
||||||
|
|
||||||
2016-03-09 10:16:35.676 [info] <0.105.0>@machi_lifecycle_mgr:process_pending_flu:422 Started FLU f1 with supervisor pid <0.128.0>
|
|
||||||
2016-03-09 10:16:35.676 [info] <0.105.0>@machi_lifecycle_mgr:move_to_flu_config:540 Creating FLU config file f1
|
|
||||||
2016-03-09 10:16:35.790 [info] <0.105.0>@machi_lifecycle_mgr:bootstrap_chain2:312 Configured chain c1 via FLU f1 to mode=ap_mode all=[f1,f2,f3] witnesses=[]
|
|
||||||
2016-03-09 10:16:35.790 [info] <0.105.0>@machi_lifecycle_mgr:move_to_chain_config:546 Creating chain config file c1
|
|
||||||
2016-03-09 10:16:44.139 [info] <0.132.0> CONFIRM epoch 1141 <<155,42,7,221>> upi [] rep [] auth f1 by f1
|
|
||||||
2016-03-09 10:16:44.271 [info] <0.132.0> CONFIRM epoch 1148 <<57,213,154,16>> upi [f1] rep [] auth f1 by f1
|
|
||||||
2016-03-09 10:16:44.864 [info] <0.132.0> CONFIRM epoch 1151 <<239,29,39,70>> upi [f1] rep [f3] auth f1 by f1
|
|
||||||
2016-03-09 10:16:45.235 [info] <0.132.0> CONFIRM epoch 1152 <<173,17,66,225>> upi [f2] rep [f1,f3] auth f2 by f1
|
|
||||||
2016-03-09 10:16:47.343 [info] <0.132.0> CONFIRM epoch 1154 <<154,231,224,149>> upi [f2,f1,f3] rep [] auth f2 by f1
|
|
||||||
|
|
||||||
Let's pick apart some of these lines. We have started all three
|
|
||||||
servers at about the same time. We see some race conditions happen,
|
|
||||||
and some jostling and readjustment happens pretty quickly in the first
|
|
||||||
few seconds.
|
|
||||||
|
|
||||||
* `Started FLU f1 with supervisor pid <0.128.0>`
|
|
||||||
* This VM, #1,
|
|
||||||
started a FLU (Machi data server) with the name `f1`. In the Erlang
|
|
||||||
process supervisor hierarchy, the process ID of the top supervisor
|
|
||||||
is `<0.128.0>`.
|
|
||||||
* `Configured chain c1 via FLU f1 to mode=ap_mode all=[f1,f2,f3] witnesses=[]`
|
|
||||||
* A bootstrap configuration for a chain named `c1` has been created.
|
|
||||||
* The FLUs/data servers that are eligible for participation in the
|
|
||||||
chain have names `f1`, `f2`, and `f3`.
|
|
||||||
* The chain will operate in eventual consistency mode (`ap_mode`)
|
|
||||||
* The witness server list is empty. Witness servers are never used
|
|
||||||
in eventual consistency mode.
|
|
||||||
* `CONFIRM epoch 1141 <<155,42,7,221>> upi [] rep [] auth f1 by f1`
|
|
||||||
* All participants in epoch 1141 are unanimous in adopting epoch
|
|
||||||
1141's projection. All active membership lists are empty, so
|
|
||||||
there is no functional chain replication yet, at least as far as
|
|
||||||
server `f1` knows
|
|
||||||
* The epoch's abbreviated checksum is `<<155,42,7,221>>`.
|
|
||||||
* The UPI list, i.e. the replicas whose data is 100% in sync is
|
|
||||||
`[]`, the empty list. (UPI = Update Propagation Invariant)
|
|
||||||
* The list of servers that are under data repair (`rep`) is also
|
|
||||||
empty, `[]`.
|
|
||||||
* This projection was authored by server `f1`.
|
|
||||||
* The log message was generated by server `f1`.
|
|
||||||
* `CONFIRM epoch 1148 <<57,213,154,16>> upi [f1] rep [] auth f1 by f1`
|
|
||||||
* Now the server `f1` has created a chain of length 1, `[f1]`.
|
|
||||||
* Chain repair/file re-sync is not required when the UPI server list
|
|
||||||
changes from length 0 -> 1.
|
|
||||||
* `CONFIRM epoch 1151 <<239,29,39,70>> upi [f1] rep [f3] auth f1 by f1`
|
|
||||||
* Server `f1` has noticed that server `f3` is alive. Apparently it
|
|
||||||
has not yet noticed that server `f2` is also running.
|
|
||||||
* Server `f3` is in the repair list.
|
|
||||||
* `CONFIRM epoch 1152 <<173,17,66,225>> upi [f2] rep [f1,f3] auth f2 by f1`
|
|
||||||
* Server `f2` is apparently now aware that all three servers are running.
|
|
||||||
* The previous configuration used by `f2` was `upi [f2]`, i.e., `f2`
|
|
||||||
was running in a chain of one. `f2` noticed that `f1` and `f3`
|
|
||||||
were now available and has started adding them to the chain.
|
|
||||||
* All new servers are always added to the tail of the chain in the
|
|
||||||
repair list.
|
|
||||||
* In eventual consistency mode, a UPI change like this is OK.
|
|
||||||
* When performing a read, a client must read from both tail of the
|
|
||||||
UPI list and also from all repairing servers.
|
|
||||||
* When performing a write, the client writes to both the UPI
|
|
||||||
server list and also the repairing list, in that order.
|
|
||||||
* I.e., the client concatenates both lists,
|
|
||||||
`UPI ++ Repairing`, for its chain configuration for the write.
|
|
||||||
* Server `f2` will trigger file repair/re-sync shortly.
|
|
||||||
* The waiting time for starting repair has been configured to be
|
|
||||||
extremely short, 1 second. The default waiting time is 10
|
|
||||||
seconds, in case Humming Consensus remains unstable.
|
|
||||||
* `CONFIRM epoch 1154 <<154,231,224,149>> upi [f2,f1,f3] rep [] auth f2 by f1`
|
|
||||||
* File repair/re-sync has finished. All file data on all servers
|
|
||||||
are now in sync.
|
|
||||||
* The UPI/in-sync part of the chain is now `[f2,f1,f3]`, and there
|
|
||||||
are no servers under repair.
|
|
||||||
|
|
||||||
## Let's create some failures
|
|
||||||
|
|
||||||
Here are some suggestions for creating failures.
|
|
||||||
|
|
||||||
* Use the `./dev/devN/bin/machi stop` and `./dev/devN/bin/machi start`
|
|
||||||
commands to stop & start VM #`N`.
|
|
||||||
* Stop a VM abnormally by using `kill`. The OS process name to look
|
|
||||||
for is `beam.smp`.
|
|
||||||
* Suspend and resume a VM, using the `SIGSTOP` and `SIGCONT` signals.
|
|
||||||
* E.g. `kill -STOP 9823` and `kill -CONT 9823`
|
|
||||||
|
|
||||||
The network partition simulator is not (yet) available when running
|
|
||||||
Machi in this mode. Please see the next section for instructions on
|
|
||||||
how to use partition simulator.
|
|
||||||
|
|
||||||
|
|
||||||
<a name="partition-simulator">
|
|
||||||
# Using the network partition simulator and convergence demo test code
|
|
||||||
|
|
||||||
This is the demo code mentioned in the presentation that Scott Lystig
|
|
||||||
Fritchie gave at the
|
|
||||||
[RICON 2015 conference](http://ricon.io).
|
|
||||||
* [slides (PDF format)](http://ricon.io/speakers/slides/Scott_Fritchie_Ricon_2015.pdf)
|
|
||||||
* [video](https://www.youtube.com/watch?v=yR5kHL1bu1Q)
|
|
||||||
|
|
||||||
## A complete example of all input and output
|
|
||||||
|
|
||||||
If you don't have an Erlang/OTP 17 runtime environment available,
|
|
||||||
please see this file for full input and output of a strong consistency
|
|
||||||
length=3 chain test:
|
|
||||||
https://gist.github.com/slfritchie/8352efc88cc18e62c72c
|
|
||||||
This file contains all commands input and all simulator output from a
|
|
||||||
sample run of the simulator.
|
|
||||||
|
|
||||||
To help interpret the output of the test, please skip ahead to the
|
|
||||||
"The test output is very verbose" section.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
If you don't have `git` and/or the Erlang 17 runtime system available
|
|
||||||
on your OS X, FreeBSD, Linux, or Solaris machine, please take a look
|
|
||||||
at the [Prerequisites section](#prerequisites) first. When you have
|
|
||||||
installed the prerequisite software, please return back here.
|
|
||||||
|
|
||||||
## Clone and compile the code
|
|
||||||
|
|
||||||
Please briefly visit the [Clone and compile the code](#clone-compile)
|
|
||||||
section. When finished, please return back here.
|
|
||||||
|
|
||||||
## Run an interactive Erlang CLI shell
|
|
||||||
|
|
||||||
Run the following command at your login shell:
|
|
||||||
|
|
||||||
erl -pz .eunit ebin deps/*/ebin
|
|
||||||
|
|
||||||
If you are using Erlang/OTP version 17, you should see some CLI output
|
|
||||||
that looks like this:
|
|
||||||
|
|
||||||
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
|
|
||||||
|
|
||||||
Eshell V6.4 (abort with ^G)
|
|
||||||
1>
|
|
||||||
|
|
||||||
## The test output is very verbose ... what are the important parts?
|
|
||||||
|
|
||||||
The output of the Erlang command
|
|
||||||
`machi_chain_manager1_converge_demo:help()` will display the following
|
|
||||||
guide to the output of the tests.
|
|
||||||
|
|
||||||
A visualization of the convergence behavior of the chain self-management
|
|
||||||
algorithm for Machi.
|
|
||||||
|
|
||||||
1. Set up some server and chain manager pairs.
|
|
||||||
2. Create a number of different network partition scenarios, where
|
|
||||||
(simulated) partitions may be symmetric or asymmetric. Then stop changing
|
|
||||||
the partitions and keep the simulated network stable (and perhaps broken).
|
|
||||||
3. Run a number of iterations of the algorithm in parallel by poking each
|
|
||||||
of the manager processes on a random'ish basis.
|
|
||||||
4. Afterward, fetch the chain transition changes made by each FLU and
|
|
||||||
verify that no transition was unsafe.
|
|
||||||
|
|
||||||
During the iteration periods, the following is a cheatsheet for the output.
|
|
||||||
See the internal source for interpreting the rest of the output.
|
|
||||||
|
|
||||||
'SET partitions = '
|
|
||||||
|
|
||||||
A pair-wise list of actors which cannot send messages. The
|
|
||||||
list is uni-directional. If there are three servers (a,b,c),
|
|
||||||
and if the partitions list is '[{a,b},{b,c}]' then all
|
|
||||||
messages from a->b and b->c will be dropped, but any other
|
|
||||||
sender->recipient messages will be delivered successfully.
|
|
||||||
|
|
||||||
'x uses:'
|
|
||||||
|
|
||||||
The FLU x has made an internal state transition and is using
|
|
||||||
this epoch's projection as operating chain configuration. The
|
|
||||||
rest of the line is a summary of the projection.
|
|
||||||
|
|
||||||
'CONFIRM epoch {N}'
|
|
||||||
|
|
||||||
This message confirms that all of the servers listed in the
|
|
||||||
UPI and repairing lists of the projection at epoch {N} have
|
|
||||||
agreed to use this projection because they all have written
|
|
||||||
this projection to their respective private projection stores.
|
|
||||||
The chain is now usable by/available to all clients.
|
|
||||||
|
|
||||||
'Sweet, private projections are stable'
|
|
||||||
|
|
||||||
This report announces that this iteration of the test cycle
|
|
||||||
has passed successfully. The report that follows briefly
|
|
||||||
summarizes the latest private projection used by each
|
|
||||||
participating server. For example, when in strong consistency
|
|
||||||
mode with 'a' as a witness and 'b' and 'c' as real servers:
|
|
||||||
|
|
||||||
%% Legend:
|
|
||||||
%% server name, epoch ID, UPI list, repairing list, down list, ...
|
|
||||||
%% ... witness list, 'false' (a constant value)
|
|
||||||
|
|
||||||
[{a,{{1116,<<23,143,246,55>>},[a,b],[],[c],[a],false}},
|
|
||||||
{b,{{1116,<<23,143,246,55>>},[a,b],[],[c],[a],false}}]
|
|
||||||
|
|
||||||
Both servers 'a' and 'b' agree on epoch 1116 with epoch ID
|
|
||||||
{1116,<<23,143,246,55>>} where UPI=[a,b], repairing=[],
|
|
||||||
down=[c], and witnesses=[a].
|
|
||||||
|
|
||||||
Server 'c' is not shown because 'c' has wedged itself OOS (out
|
|
||||||
of service) by configuring a chain length of zero.
|
|
||||||
|
|
||||||
If no servers are listed in the report (i.e. only '[]' is
|
|
||||||
displayed), then all servers have wedged themselves OOS, and
|
|
||||||
the chain is unavailable.
|
|
||||||
|
|
||||||
'DoIt,'
|
|
||||||
|
|
||||||
This marks a group of tick events which trigger the manager
|
|
||||||
processes to evaluate their environment and perhaps make a
|
|
||||||
state transition.
|
|
||||||
|
|
||||||
A long chain of 'DoIt,DoIt,DoIt,' means that the chain state has
|
|
||||||
(probably) settled to a stable configuration, which is the goal of the
|
|
||||||
algorithm.
|
|
||||||
|
|
||||||
Press control-c to interrupt the test....".
|
|
||||||
|
|
||||||
## Run a test in eventual consistency mode
|
|
||||||
|
|
||||||
Run the following command at the Erlang CLI prompt:
|
|
||||||
|
|
||||||
machi_chain_manager1_converge_demo:t(3, [{private_write_verbose,true}]).
|
|
||||||
|
|
||||||
The first argument, `3`, is the number of servers to participate in
|
|
||||||
the chain. Please note:
|
|
||||||
|
|
||||||
* Chain lengths as short as 1 or 2 are valid, but the results are a
|
|
||||||
bit boring.
|
|
||||||
* Chain lengths as long as 7 or 9 can be used, but they may
|
|
||||||
suffer from longer periods of churn/instability before all chain
|
|
||||||
managers reach agreement via humming consensus. (It is future work
|
|
||||||
to shorten the worst of the unstable churn latencies.)
|
|
||||||
* In eventual consistency mode, chain lengths may be even numbers,
|
|
||||||
e.g. 2, 4, or 6.
|
|
||||||
* The simulator will choose partition events from the permutations of
|
|
||||||
all 1, 2, and 3 node partition pairs. The total runtime will
|
|
||||||
increase *dramatically* with chain length.
|
|
||||||
* Chain length 2: about 3 partition cases
|
|
||||||
* Chain length 3: about 35 partition cases
|
|
||||||
* Chain length 4: about 230 partition cases
|
|
||||||
* Chain length 5: about 1100 partition cases
|
|
||||||
|
|
||||||
## Run a test in strong consistency mode (with witnesses):
|
|
||||||
|
|
||||||
*NOTE:* Due to a bug in the test code, please do not try to run the
|
|
||||||
convergence test in strong consistency mode and also without the
|
|
||||||
correct minority number of witness servers! If in doubt, please run
|
|
||||||
the commands shown below exactly.
|
|
||||||
|
|
||||||
Run the following command at the Erlang CLI prompt:
|
|
||||||
|
|
||||||
machi_chain_manager1_converge_demo:t(3, [{private_write_verbose,true}, {consistency_mode, cp_mode}, {witnesses, [a]}]).
|
|
||||||
|
|
||||||
The first argument, `3`, is the number of servers to participate in
|
|
||||||
the chain. Chain lengths as long as 7 or 9 can be used, but they may
|
|
||||||
suffer from longer periods of churn/instability before all chain
|
|
||||||
managers reach agreement via humming consensus.
|
|
||||||
|
|
||||||
Due to the bug mentioned above, please use the following
|
|
||||||
commands when running with chain lengths of 5 or 7, respectively.
|
|
||||||
|
|
||||||
machi_chain_manager1_converge_demo:t(5, [{private_write_verbose,true}, {consistency_mode, cp_mode}, {witnesses, [a,b]}]).
|
|
||||||
machi_chain_manager1_converge_demo:t(7, [{private_write_verbose,true}, {consistency_mode, cp_mode}, {witnesses, [a,b,c]}]).
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 115 KiB |
4
doc/src.high-level/.gitignore
vendored
4
doc/src.high-level/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
*.aux
|
|
||||||
*.dvi
|
|
||||||
*.log
|
|
||||||
*.pdf
|
|
|
@ -1,12 +0,0 @@
|
||||||
all: machi chain-mgr
|
|
||||||
|
|
||||||
machi:
|
|
||||||
latex high-level-machi.tex
|
|
||||||
dvipdfm high-level-machi.dvi
|
|
||||||
|
|
||||||
chain-mgr:
|
|
||||||
latex high-level-chain-mgr.tex
|
|
||||||
dvipdfm high-level-chain-mgr.dvi
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.aux *.dvi *.log
|
|
|
@ -1,268 +0,0 @@
|
||||||
%!PS-Adobe-3.0 EPSF-2.0
|
|
||||||
%%BoundingBox: 0 0 416.500000 280.000000
|
|
||||||
%%Creator: mscgen 0.18
|
|
||||||
%%EndComments
|
|
||||||
0.700000 0.700000 scale
|
|
||||||
0 0 moveto
|
|
||||||
0 400 lineto
|
|
||||||
595 400 lineto
|
|
||||||
595 0 lineto
|
|
||||||
closepath
|
|
||||||
clip
|
|
||||||
%PageTrailer
|
|
||||||
%Page: 1 1
|
|
||||||
/Helvetica findfont
|
|
||||||
10 scalefont
|
|
||||||
setfont
|
|
||||||
/Helvetica findfont
|
|
||||||
12 scalefont
|
|
||||||
setfont
|
|
||||||
0 400 translate
|
|
||||||
/mtrx matrix def
|
|
||||||
/ellipse
|
|
||||||
{ /endangle exch def
|
|
||||||
/startangle exch def
|
|
||||||
/ydia exch def
|
|
||||||
/xdia exch def
|
|
||||||
/y exch def
|
|
||||||
/x exch def
|
|
||||||
/savematrix mtrx currentmatrix def
|
|
||||||
x y translate
|
|
||||||
xdia 2 div ydia 2 div scale
|
|
||||||
1 -1 scale
|
|
||||||
0 0 1 startangle endangle arc
|
|
||||||
savematrix setmatrix
|
|
||||||
} def
|
|
||||||
(client) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 42 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
42 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(Projection) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 127 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
127 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(ProjStore_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 212 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
212 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(Sequencer_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 297 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
297 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 382 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
382 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_B) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 467 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
467 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_C) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 552 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
552 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
newpath 42 -22 moveto 42 -49 lineto stroke
|
|
||||||
newpath 127 -22 moveto 127 -49 lineto stroke
|
|
||||||
newpath 212 -22 moveto 212 -49 lineto stroke
|
|
||||||
newpath 297 -22 moveto 297 -49 lineto stroke
|
|
||||||
newpath 382 -22 moveto 382 -49 lineto stroke
|
|
||||||
newpath 467 -22 moveto 467 -49 lineto stroke
|
|
||||||
newpath 552 -22 moveto 552 -49 lineto stroke
|
|
||||||
newpath 42 -35 moveto 127 -35 lineto stroke
|
|
||||||
newpath 127 -35 moveto 117 -41 lineto stroke
|
|
||||||
(get current) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 57 -33 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
57 -33 moveto show
|
|
||||||
newpath 42 -49 moveto 42 -76 lineto stroke
|
|
||||||
newpath 127 -49 moveto 127 -76 lineto stroke
|
|
||||||
newpath 212 -49 moveto 212 -76 lineto stroke
|
|
||||||
newpath 297 -49 moveto 297 -76 lineto stroke
|
|
||||||
newpath 382 -49 moveto 382 -76 lineto stroke
|
|
||||||
newpath 467 -49 moveto 467 -76 lineto stroke
|
|
||||||
newpath 552 -49 moveto 552 -76 lineto stroke
|
|
||||||
newpath 127 -62 moveto 42 -62 lineto stroke
|
|
||||||
newpath 42 -62 moveto 52 -68 lineto stroke
|
|
||||||
(ok, #12...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 61 -60 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
61 -60 moveto show
|
|
||||||
newpath 42 -76 moveto 42 -103 lineto stroke
|
|
||||||
newpath 127 -76 moveto 127 -103 lineto stroke
|
|
||||||
newpath 212 -76 moveto 212 -103 lineto stroke
|
|
||||||
newpath 297 -76 moveto 297 -103 lineto stroke
|
|
||||||
newpath 382 -76 moveto 382 -103 lineto stroke
|
|
||||||
newpath 467 -76 moveto 467 -103 lineto stroke
|
|
||||||
newpath 552 -76 moveto 552 -103 lineto stroke
|
|
||||||
newpath 42 -89 moveto 297 -89 lineto stroke
|
|
||||||
newpath 297 -89 moveto 287 -95 lineto stroke
|
|
||||||
(Req. 123 bytes, prefix="foo", epoch=12) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 66 -87 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
66 -87 moveto show
|
|
||||||
newpath 42 -103 moveto 42 -130 lineto stroke
|
|
||||||
newpath 127 -103 moveto 127 -130 lineto stroke
|
|
||||||
newpath 212 -103 moveto 212 -130 lineto stroke
|
|
||||||
newpath 297 -103 moveto 297 -130 lineto stroke
|
|
||||||
newpath 382 -103 moveto 382 -130 lineto stroke
|
|
||||||
newpath 467 -103 moveto 467 -130 lineto stroke
|
|
||||||
newpath 552 -103 moveto 552 -130 lineto stroke
|
|
||||||
newpath 297 -116 moveto 42 -116 lineto stroke
|
|
||||||
newpath 42 -116 moveto 52 -122 lineto stroke
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
(bad_epoch, 13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 131 -114 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
131 -114 moveto show
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
newpath 42 -130 moveto 42 -157 lineto stroke
|
|
||||||
newpath 127 -130 moveto 127 -157 lineto stroke
|
|
||||||
newpath 212 -130 moveto 212 -157 lineto stroke
|
|
||||||
newpath 297 -130 moveto 297 -157 lineto stroke
|
|
||||||
newpath 382 -130 moveto 382 -157 lineto stroke
|
|
||||||
newpath 467 -130 moveto 467 -157 lineto stroke
|
|
||||||
newpath 552 -130 moveto 552 -157 lineto stroke
|
|
||||||
newpath 42 -143 moveto 212 -143 lineto stroke
|
|
||||||
newpath 212 -143 moveto 202 -149 lineto stroke
|
|
||||||
(get epoch #13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 89 -141 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
89 -141 moveto show
|
|
||||||
newpath 42 -157 moveto 42 -184 lineto stroke
|
|
||||||
newpath 127 -157 moveto 127 -184 lineto stroke
|
|
||||||
newpath 212 -157 moveto 212 -184 lineto stroke
|
|
||||||
newpath 297 -157 moveto 297 -184 lineto stroke
|
|
||||||
newpath 382 -157 moveto 382 -184 lineto stroke
|
|
||||||
newpath 467 -157 moveto 467 -184 lineto stroke
|
|
||||||
newpath 552 -157 moveto 552 -184 lineto stroke
|
|
||||||
newpath 212 -170 moveto 42 -170 lineto stroke
|
|
||||||
newpath 42 -170 moveto 52 -176 lineto stroke
|
|
||||||
(ok, #13...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 103 -168 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
103 -168 moveto show
|
|
||||||
newpath 42 -184 moveto 42 -211 lineto stroke
|
|
||||||
newpath 127 -184 moveto 127 -211 lineto stroke
|
|
||||||
newpath 212 -184 moveto 212 -211 lineto stroke
|
|
||||||
newpath 297 -184 moveto 297 -211 lineto stroke
|
|
||||||
newpath 382 -184 moveto 382 -211 lineto stroke
|
|
||||||
newpath 467 -184 moveto 467 -211 lineto stroke
|
|
||||||
newpath 552 -184 moveto 552 -211 lineto stroke
|
|
||||||
newpath 42 -197 moveto 297 -197 lineto stroke
|
|
||||||
newpath 297 -197 moveto 287 -203 lineto stroke
|
|
||||||
(Req. 123 bytes, prefix="foo", epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 66 -195 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
66 -195 moveto show
|
|
||||||
newpath 42 -211 moveto 42 -238 lineto stroke
|
|
||||||
newpath 127 -211 moveto 127 -238 lineto stroke
|
|
||||||
newpath 212 -211 moveto 212 -238 lineto stroke
|
|
||||||
newpath 297 -211 moveto 297 -238 lineto stroke
|
|
||||||
newpath 382 -211 moveto 382 -238 lineto stroke
|
|
||||||
newpath 467 -211 moveto 467 -238 lineto stroke
|
|
||||||
newpath 552 -211 moveto 552 -238 lineto stroke
|
|
||||||
newpath 297 -224 moveto 42 -224 lineto stroke
|
|
||||||
newpath 42 -224 moveto 52 -230 lineto stroke
|
|
||||||
(ok, "foo.seq_a.009" offset=447) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 89 -222 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
89 -222 moveto show
|
|
||||||
newpath 42 -238 moveto 42 -265 lineto stroke
|
|
||||||
newpath 127 -238 moveto 127 -265 lineto stroke
|
|
||||||
newpath 212 -238 moveto 212 -265 lineto stroke
|
|
||||||
newpath 297 -238 moveto 297 -265 lineto stroke
|
|
||||||
newpath 382 -238 moveto 382 -265 lineto stroke
|
|
||||||
newpath 467 -238 moveto 467 -265 lineto stroke
|
|
||||||
newpath 552 -238 moveto 552 -265 lineto stroke
|
|
||||||
newpath 42 -251 moveto 382 -251 lineto stroke
|
|
||||||
newpath 382 -251 moveto 372 -257 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 51 -249 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
51 -249 moveto show
|
|
||||||
newpath 42 -265 moveto 42 -292 lineto stroke
|
|
||||||
newpath 127 -265 moveto 127 -292 lineto stroke
|
|
||||||
newpath 212 -265 moveto 212 -292 lineto stroke
|
|
||||||
newpath 297 -265 moveto 297 -292 lineto stroke
|
|
||||||
newpath 382 -265 moveto 382 -292 lineto stroke
|
|
||||||
newpath 467 -265 moveto 467 -292 lineto stroke
|
|
||||||
newpath 552 -265 moveto 552 -292 lineto stroke
|
|
||||||
newpath 382 -278 moveto 42 -278 lineto stroke
|
|
||||||
newpath 42 -278 moveto 52 -284 lineto stroke
|
|
||||||
(ok) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 206 -276 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
206 -276 moveto show
|
|
||||||
newpath 42 -292 moveto 42 -319 lineto stroke
|
|
||||||
newpath 127 -292 moveto 127 -319 lineto stroke
|
|
||||||
newpath 212 -292 moveto 212 -319 lineto stroke
|
|
||||||
newpath 297 -292 moveto 297 -319 lineto stroke
|
|
||||||
newpath 382 -292 moveto 382 -319 lineto stroke
|
|
||||||
newpath 467 -292 moveto 467 -319 lineto stroke
|
|
||||||
newpath 552 -292 moveto 552 -319 lineto stroke
|
|
||||||
newpath 42 -305 moveto 467 -305 lineto stroke
|
|
||||||
newpath 467 -305 moveto 457 -311 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 94 -303 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
94 -303 moveto show
|
|
||||||
newpath 42 -319 moveto 42 -346 lineto stroke
|
|
||||||
newpath 127 -319 moveto 127 -346 lineto stroke
|
|
||||||
newpath 212 -319 moveto 212 -346 lineto stroke
|
|
||||||
newpath 297 -319 moveto 297 -346 lineto stroke
|
|
||||||
newpath 382 -319 moveto 382 -346 lineto stroke
|
|
||||||
newpath 467 -319 moveto 467 -346 lineto stroke
|
|
||||||
newpath 552 -319 moveto 552 -346 lineto stroke
|
|
||||||
newpath 467 -332 moveto 42 -332 lineto stroke
|
|
||||||
newpath 42 -332 moveto 52 -338 lineto stroke
|
|
||||||
(ok) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 249 -330 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
249 -330 moveto show
|
|
||||||
newpath 42 -346 moveto 42 -373 lineto stroke
|
|
||||||
newpath 127 -346 moveto 127 -373 lineto stroke
|
|
||||||
newpath 212 -346 moveto 212 -373 lineto stroke
|
|
||||||
newpath 297 -346 moveto 297 -373 lineto stroke
|
|
||||||
newpath 382 -346 moveto 382 -373 lineto stroke
|
|
||||||
newpath 467 -346 moveto 467 -373 lineto stroke
|
|
||||||
newpath 552 -346 moveto 552 -373 lineto stroke
|
|
||||||
newpath 42 -359 moveto 552 -359 lineto stroke
|
|
||||||
newpath 552 -359 moveto 542 -365 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 136 -357 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
136 -357 moveto show
|
|
||||||
newpath 42 -373 moveto 42 -400 lineto stroke
|
|
||||||
newpath 127 -373 moveto 127 -400 lineto stroke
|
|
||||||
newpath 212 -373 moveto 212 -400 lineto stroke
|
|
||||||
newpath 297 -373 moveto 297 -400 lineto stroke
|
|
||||||
newpath 382 -373 moveto 382 -400 lineto stroke
|
|
||||||
newpath 467 -373 moveto 467 -400 lineto stroke
|
|
||||||
newpath 552 -373 moveto 552 -400 lineto stroke
|
|
||||||
newpath 552 -386 moveto 42 -386 lineto stroke
|
|
||||||
newpath 42 -386 moveto 52 -392 lineto stroke
|
|
||||||
(ok) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 291 -384 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
291 -384 moveto show
|
|
|
@ -1,345 +0,0 @@
|
||||||
%!PS-Adobe-3.0 EPSF-2.0
|
|
||||||
%%BoundingBox: 0 0 416.500000 355.600006
|
|
||||||
%%Creator: mscgen 0.18
|
|
||||||
%%EndComments
|
|
||||||
0.700000 0.700000 scale
|
|
||||||
0 0 moveto
|
|
||||||
0 508 lineto
|
|
||||||
595 508 lineto
|
|
||||||
595 0 lineto
|
|
||||||
closepath
|
|
||||||
clip
|
|
||||||
%PageTrailer
|
|
||||||
%Page: 1 1
|
|
||||||
/Helvetica findfont
|
|
||||||
10 scalefont
|
|
||||||
setfont
|
|
||||||
/Helvetica findfont
|
|
||||||
12 scalefont
|
|
||||||
setfont
|
|
||||||
0 508 translate
|
|
||||||
/mtrx matrix def
|
|
||||||
/ellipse
|
|
||||||
{ /endangle exch def
|
|
||||||
/startangle exch def
|
|
||||||
/ydia exch def
|
|
||||||
/xdia exch def
|
|
||||||
/y exch def
|
|
||||||
/x exch def
|
|
||||||
/savematrix mtrx currentmatrix def
|
|
||||||
x y translate
|
|
||||||
xdia 2 div ydia 2 div scale
|
|
||||||
1 -1 scale
|
|
||||||
0 0 1 startangle endangle arc
|
|
||||||
savematrix setmatrix
|
|
||||||
} def
|
|
||||||
(client) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 42 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
42 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(Projection) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 127 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
127 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(ProjStore_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 212 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
212 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(Sequencer_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 297 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
297 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_A) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 382 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
382 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_B) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 467 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
467 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_C) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 552 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
552 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
newpath 42 -22 moveto 42 -49 lineto stroke
|
|
||||||
newpath 127 -22 moveto 127 -49 lineto stroke
|
|
||||||
newpath 212 -22 moveto 212 -49 lineto stroke
|
|
||||||
newpath 297 -22 moveto 297 -49 lineto stroke
|
|
||||||
newpath 382 -22 moveto 382 -49 lineto stroke
|
|
||||||
newpath 467 -22 moveto 467 -49 lineto stroke
|
|
||||||
newpath 552 -22 moveto 552 -49 lineto stroke
|
|
||||||
newpath 42 -35 moveto 127 -35 lineto stroke
|
|
||||||
newpath 127 -35 moveto 117 -41 lineto stroke
|
|
||||||
(get current) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 57 -33 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
57 -33 moveto show
|
|
||||||
newpath 42 -49 moveto 42 -76 lineto stroke
|
|
||||||
newpath 127 -49 moveto 127 -76 lineto stroke
|
|
||||||
newpath 212 -49 moveto 212 -76 lineto stroke
|
|
||||||
newpath 297 -49 moveto 297 -76 lineto stroke
|
|
||||||
newpath 382 -49 moveto 382 -76 lineto stroke
|
|
||||||
newpath 467 -49 moveto 467 -76 lineto stroke
|
|
||||||
newpath 552 -49 moveto 552 -76 lineto stroke
|
|
||||||
newpath 127 -62 moveto 42 -62 lineto stroke
|
|
||||||
newpath 42 -62 moveto 52 -68 lineto stroke
|
|
||||||
(ok, #12...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 61 -60 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
61 -60 moveto show
|
|
||||||
newpath 42 -76 moveto 42 -103 lineto stroke
|
|
||||||
newpath 127 -76 moveto 127 -103 lineto stroke
|
|
||||||
newpath 212 -76 moveto 212 -103 lineto stroke
|
|
||||||
newpath 297 -76 moveto 297 -103 lineto stroke
|
|
||||||
newpath 382 -76 moveto 382 -103 lineto stroke
|
|
||||||
newpath 467 -76 moveto 467 -103 lineto stroke
|
|
||||||
newpath 552 -76 moveto 552 -103 lineto stroke
|
|
||||||
newpath 42 -89 moveto 382 -89 lineto stroke
|
|
||||||
newpath 382 -89 moveto 372 -95 lineto stroke
|
|
||||||
(append prefix="foo" <<123 bytes...>> epoch=12) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 85 -87 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
85 -87 moveto show
|
|
||||||
newpath 42 -103 moveto 42 -130 lineto stroke
|
|
||||||
newpath 127 -103 moveto 127 -130 lineto stroke
|
|
||||||
newpath 212 -103 moveto 212 -130 lineto stroke
|
|
||||||
newpath 297 -103 moveto 297 -130 lineto stroke
|
|
||||||
newpath 382 -103 moveto 382 -130 lineto stroke
|
|
||||||
newpath 467 -103 moveto 467 -130 lineto stroke
|
|
||||||
newpath 552 -103 moveto 552 -130 lineto stroke
|
|
||||||
newpath 382 -116 moveto 42 -116 lineto stroke
|
|
||||||
newpath 42 -116 moveto 52 -122 lineto stroke
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
(bad_epoch, 13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 173 -114 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
173 -114 moveto show
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
newpath 42 -130 moveto 42 -157 lineto stroke
|
|
||||||
newpath 127 -130 moveto 127 -157 lineto stroke
|
|
||||||
newpath 212 -130 moveto 212 -157 lineto stroke
|
|
||||||
newpath 297 -130 moveto 297 -157 lineto stroke
|
|
||||||
newpath 382 -130 moveto 382 -157 lineto stroke
|
|
||||||
newpath 467 -130 moveto 467 -157 lineto stroke
|
|
||||||
newpath 552 -130 moveto 552 -157 lineto stroke
|
|
||||||
newpath 42 -143 moveto 212 -143 lineto stroke
|
|
||||||
newpath 212 -143 moveto 202 -149 lineto stroke
|
|
||||||
(get epoch #13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 89 -141 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
89 -141 moveto show
|
|
||||||
newpath 42 -157 moveto 42 -184 lineto stroke
|
|
||||||
newpath 127 -157 moveto 127 -184 lineto stroke
|
|
||||||
newpath 212 -157 moveto 212 -184 lineto stroke
|
|
||||||
newpath 297 -157 moveto 297 -184 lineto stroke
|
|
||||||
newpath 382 -157 moveto 382 -184 lineto stroke
|
|
||||||
newpath 467 -157 moveto 467 -184 lineto stroke
|
|
||||||
newpath 552 -157 moveto 552 -184 lineto stroke
|
|
||||||
newpath 212 -170 moveto 42 -170 lineto stroke
|
|
||||||
newpath 42 -170 moveto 52 -176 lineto stroke
|
|
||||||
(ok, #13...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 103 -168 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
103 -168 moveto show
|
|
||||||
newpath 42 -184 moveto 42 -211 lineto stroke
|
|
||||||
newpath 127 -184 moveto 127 -211 lineto stroke
|
|
||||||
newpath 212 -184 moveto 212 -211 lineto stroke
|
|
||||||
newpath 297 -184 moveto 297 -211 lineto stroke
|
|
||||||
newpath 382 -184 moveto 382 -211 lineto stroke
|
|
||||||
newpath 467 -184 moveto 467 -211 lineto stroke
|
|
||||||
newpath 552 -184 moveto 552 -211 lineto stroke
|
|
||||||
newpath 42 -197 moveto 382 -197 lineto stroke
|
|
||||||
newpath 382 -197 moveto 372 -203 lineto stroke
|
|
||||||
(append prefix="foo" <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 85 -195 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
85 -195 moveto show
|
|
||||||
newpath 42 -211 moveto 42 -238 lineto stroke
|
|
||||||
newpath 127 -211 moveto 127 -238 lineto stroke
|
|
||||||
newpath 212 -211 moveto 212 -238 lineto stroke
|
|
||||||
newpath 297 -211 moveto 297 -238 lineto stroke
|
|
||||||
newpath 382 -211 moveto 382 -238 lineto stroke
|
|
||||||
newpath 467 -211 moveto 467 -238 lineto stroke
|
|
||||||
newpath 552 -211 moveto 552 -238 lineto stroke
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
newpath 263 -211 moveto 417 -211 lineto 417 -236 lineto 263 -236 lineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
newpath 269 -211 moveto 411 -211 lineto stroke
|
|
||||||
newpath 269 -236 moveto 411 -236 lineto stroke
|
|
||||||
newpath 269 -211 moveto 263 -223 lineto stroke
|
|
||||||
newpath 263 -223 moveto 269 -236 lineto stroke
|
|
||||||
newpath 411 -211 moveto 417 -223 lineto stroke
|
|
||||||
newpath 417 -223 moveto 411 -236 lineto stroke
|
|
||||||
(Co-located on same box) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 275 -227 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
275 -227 moveto show
|
|
||||||
newpath 42 -238 moveto 42 -265 lineto stroke
|
|
||||||
newpath 127 -238 moveto 127 -265 lineto stroke
|
|
||||||
newpath 212 -238 moveto 212 -265 lineto stroke
|
|
||||||
newpath 297 -238 moveto 297 -265 lineto stroke
|
|
||||||
newpath 382 -238 moveto 382 -265 lineto stroke
|
|
||||||
newpath 467 -238 moveto 467 -265 lineto stroke
|
|
||||||
newpath 552 -238 moveto 552 -265 lineto stroke
|
|
||||||
newpath 382 -251 moveto 297 -251 lineto stroke
|
|
||||||
newpath 297 -251 moveto 307 -257 lineto stroke
|
|
||||||
(Req. 123 bytes, prefix="foo", epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 236 -249 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
236 -249 moveto show
|
|
||||||
newpath 42 -265 moveto 42 -292 lineto stroke
|
|
||||||
newpath 127 -265 moveto 127 -292 lineto stroke
|
|
||||||
newpath 212 -265 moveto 212 -292 lineto stroke
|
|
||||||
newpath 297 -265 moveto 297 -292 lineto stroke
|
|
||||||
newpath 382 -265 moveto 382 -292 lineto stroke
|
|
||||||
newpath 467 -265 moveto 467 -292 lineto stroke
|
|
||||||
newpath 552 -265 moveto 552 -292 lineto stroke
|
|
||||||
newpath 297 -278 moveto 382 -278 lineto stroke
|
|
||||||
newpath 382 -278 moveto 372 -284 lineto stroke
|
|
||||||
(ok, "foo.seq_a.009" offset=447) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 259 -276 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
259 -276 moveto show
|
|
||||||
newpath 42 -292 moveto 42 -319 lineto stroke
|
|
||||||
newpath 127 -292 moveto 127 -319 lineto stroke
|
|
||||||
newpath 212 -292 moveto 212 -319 lineto stroke
|
|
||||||
newpath 297 -292 moveto 297 -319 lineto stroke
|
|
||||||
newpath 382 -292 moveto 382 -319 lineto stroke
|
|
||||||
newpath 467 -292 moveto 467 -319 lineto stroke
|
|
||||||
newpath 552 -292 moveto 552 -319 lineto stroke
|
|
||||||
newpath 382 -305 85 13 270 90 ellipse stroke
|
|
||||||
newpath 382 -311 moveto 392 -317 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 58 -303 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
58 -303 moveto show
|
|
||||||
newpath 42 -319 moveto 42 -346 lineto stroke
|
|
||||||
newpath 127 -319 moveto 127 -346 lineto stroke
|
|
||||||
newpath 212 -319 moveto 212 -346 lineto stroke
|
|
||||||
newpath 297 -319 moveto 297 -346 lineto stroke
|
|
||||||
newpath 382 -319 moveto 382 -346 lineto stroke
|
|
||||||
newpath 467 -319 moveto 467 -346 lineto stroke
|
|
||||||
newpath 552 -319 moveto 552 -346 lineto stroke
|
|
||||||
newpath 382 -332 moveto 467 -332 lineto stroke
|
|
||||||
newpath 467 -332 moveto 457 -338 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 264 -330 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
264 -330 moveto show
|
|
||||||
newpath 42 -346 moveto 42 -373 lineto stroke
|
|
||||||
newpath 127 -346 moveto 127 -373 lineto stroke
|
|
||||||
newpath 212 -346 moveto 212 -373 lineto stroke
|
|
||||||
newpath 297 -346 moveto 297 -373 lineto stroke
|
|
||||||
newpath 382 -346 moveto 382 -373 lineto stroke
|
|
||||||
newpath 467 -346 moveto 467 -373 lineto stroke
|
|
||||||
newpath 552 -346 moveto 552 -373 lineto stroke
|
|
||||||
newpath 467 -359 moveto 552 -359 lineto stroke
|
|
||||||
newpath 552 -359 moveto 542 -365 lineto stroke
|
|
||||||
(write "foo.seq_a.009" offset=447 <<123 bytes...>> epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 273 -357 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
273 -357 moveto show
|
|
||||||
newpath 42 -373 moveto 42 -400 lineto stroke
|
|
||||||
newpath 127 -373 moveto 127 -400 lineto stroke
|
|
||||||
newpath 212 -373 moveto 212 -400 lineto stroke
|
|
||||||
newpath 297 -373 moveto 297 -400 lineto stroke
|
|
||||||
newpath 382 -373 moveto 382 -400 lineto stroke
|
|
||||||
newpath 467 -373 moveto 467 -400 lineto stroke
|
|
||||||
newpath 552 -373 moveto 552 -400 lineto stroke
|
|
||||||
newpath 552 -386 moveto 42 -386 lineto stroke
|
|
||||||
newpath 42 -386 moveto 52 -392 lineto stroke
|
|
||||||
(ok, "foo.seq_a.009" offset=447) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 216 -384 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
216 -384 moveto show
|
|
||||||
newpath 42 -400 moveto 42 -427 lineto stroke
|
|
||||||
newpath 127 -400 moveto 127 -427 lineto stroke
|
|
||||||
newpath 212 -400 moveto 212 -427 lineto stroke
|
|
||||||
newpath 297 -400 moveto 297 -427 lineto stroke
|
|
||||||
newpath 382 -400 moveto 382 -427 lineto stroke
|
|
||||||
newpath 467 -400 moveto 467 -427 lineto stroke
|
|
||||||
newpath 552 -400 moveto 552 -427 lineto stroke
|
|
||||||
(The above is "fast path" for FLU->FLU forwarding.) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 164 -416 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
164 -416 moveto show
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 21 -413 moveto 162 -413 lineto stroke
|
|
||||||
[] 0 setdash
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 432 -413 moveto 574 -413 lineto stroke
|
|
||||||
[] 0 setdash
|
|
||||||
newpath 42 -427 moveto 42 -454 lineto stroke
|
|
||||||
newpath 127 -427 moveto 127 -454 lineto stroke
|
|
||||||
newpath 212 -427 moveto 212 -454 lineto stroke
|
|
||||||
newpath 297 -427 moveto 297 -454 lineto stroke
|
|
||||||
newpath 382 -427 moveto 382 -454 lineto stroke
|
|
||||||
newpath 467 -427 moveto 467 -454 lineto stroke
|
|
||||||
newpath 552 -427 moveto 552 -454 lineto stroke
|
|
||||||
(If, in an alternate scenario, FLU_C has an error...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 167 -443 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
167 -443 moveto show
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 21 -440 moveto 165 -440 lineto stroke
|
|
||||||
[] 0 setdash
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 429 -440 moveto 574 -440 lineto stroke
|
|
||||||
[] 0 setdash
|
|
||||||
newpath 42 -454 moveto 42 -481 lineto stroke
|
|
||||||
newpath 127 -454 moveto 127 -481 lineto stroke
|
|
||||||
newpath 212 -454 moveto 212 -481 lineto stroke
|
|
||||||
newpath 297 -454 moveto 297 -481 lineto stroke
|
|
||||||
newpath 382 -454 moveto 382 -481 lineto stroke
|
|
||||||
newpath 467 -454 moveto 467 -481 lineto stroke
|
|
||||||
newpath 552 -454 moveto 552 -481 lineto stroke
|
|
||||||
newpath 552 -467 moveto 42 -467 lineto stroke
|
|
||||||
newpath 42 -467 moveto 52 -473 lineto stroke
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
(bad_epoch, 15) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 258 -465 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
258 -465 moveto show
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
newpath 42 -481 moveto 42 -508 lineto stroke
|
|
||||||
newpath 127 -481 moveto 127 -508 lineto stroke
|
|
||||||
newpath 212 -481 moveto 212 -508 lineto stroke
|
|
||||||
newpath 297 -481 moveto 297 -508 lineto stroke
|
|
||||||
newpath 382 -481 moveto 382 -508 lineto stroke
|
|
||||||
newpath 467 -481 moveto 467 -508 lineto stroke
|
|
||||||
newpath 552 -481 moveto 552 -508 lineto stroke
|
|
||||||
(... then repair becomes the client's responsibility \("slow path"\).) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 133 -497 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
133 -497 moveto show
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 21 -494 moveto 131 -494 lineto stroke
|
|
||||||
[] 0 setdash
|
|
||||||
[2] 0 setdash
|
|
||||||
newpath 464 -494 moveto 574 -494 lineto stroke
|
|
||||||
[] 0 setdash
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,557 +0,0 @@
|
||||||
%!PS-Adobe-3.0 EPSF-3.0
|
|
||||||
%%Title: figure6.fig
|
|
||||||
%%Creator: fig2dev Version 3.2 Patchlevel 5d
|
|
||||||
%%CreationDate: Mon Oct 20 21:56:33 2014
|
|
||||||
%%For: fritchie@sbb3.local (Scott Lystig Fritchie)
|
|
||||||
%%BoundingBox: 0 0 633 332
|
|
||||||
%Magnification: 1.0000
|
|
||||||
%%EndComments
|
|
||||||
%%BeginProlog
|
|
||||||
/$F2psDict 200 dict def
|
|
||||||
$F2psDict begin
|
|
||||||
$F2psDict /mtrx matrix put
|
|
||||||
/col-1 {0 setgray} bind def
|
|
||||||
/col0 {0.000 0.000 0.000 srgb} bind def
|
|
||||||
/col1 {0.000 0.000 1.000 srgb} bind def
|
|
||||||
/col2 {0.000 1.000 0.000 srgb} bind def
|
|
||||||
/col3 {0.000 1.000 1.000 srgb} bind def
|
|
||||||
/col4 {1.000 0.000 0.000 srgb} bind def
|
|
||||||
/col5 {1.000 0.000 1.000 srgb} bind def
|
|
||||||
/col6 {1.000 1.000 0.000 srgb} bind def
|
|
||||||
/col7 {1.000 1.000 1.000 srgb} bind def
|
|
||||||
/col8 {0.000 0.000 0.560 srgb} bind def
|
|
||||||
/col9 {0.000 0.000 0.690 srgb} bind def
|
|
||||||
/col10 {0.000 0.000 0.820 srgb} bind def
|
|
||||||
/col11 {0.530 0.810 1.000 srgb} bind def
|
|
||||||
/col12 {0.000 0.560 0.000 srgb} bind def
|
|
||||||
/col13 {0.000 0.690 0.000 srgb} bind def
|
|
||||||
/col14 {0.000 0.820 0.000 srgb} bind def
|
|
||||||
/col15 {0.000 0.560 0.560 srgb} bind def
|
|
||||||
/col16 {0.000 0.690 0.690 srgb} bind def
|
|
||||||
/col17 {0.000 0.820 0.820 srgb} bind def
|
|
||||||
/col18 {0.560 0.000 0.000 srgb} bind def
|
|
||||||
/col19 {0.690 0.000 0.000 srgb} bind def
|
|
||||||
/col20 {0.820 0.000 0.000 srgb} bind def
|
|
||||||
/col21 {0.560 0.000 0.560 srgb} bind def
|
|
||||||
/col22 {0.690 0.000 0.690 srgb} bind def
|
|
||||||
/col23 {0.820 0.000 0.820 srgb} bind def
|
|
||||||
/col24 {0.500 0.190 0.000 srgb} bind def
|
|
||||||
/col25 {0.630 0.250 0.000 srgb} bind def
|
|
||||||
/col26 {0.750 0.380 0.000 srgb} bind def
|
|
||||||
/col27 {1.000 0.500 0.500 srgb} bind def
|
|
||||||
/col28 {1.000 0.630 0.630 srgb} bind def
|
|
||||||
/col29 {1.000 0.750 0.750 srgb} bind def
|
|
||||||
/col30 {1.000 0.880 0.880 srgb} bind def
|
|
||||||
/col31 {1.000 0.840 0.000 srgb} bind def
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
/cp {closepath} bind def
|
|
||||||
/ef {eofill} bind def
|
|
||||||
/gr {grestore} bind def
|
|
||||||
/gs {gsave} bind def
|
|
||||||
/sa {save} bind def
|
|
||||||
/rs {restore} bind def
|
|
||||||
/l {lineto} bind def
|
|
||||||
/m {moveto} bind def
|
|
||||||
/rm {rmoveto} bind def
|
|
||||||
/n {newpath} bind def
|
|
||||||
/s {stroke} bind def
|
|
||||||
/sh {show} bind def
|
|
||||||
/slc {setlinecap} bind def
|
|
||||||
/slj {setlinejoin} bind def
|
|
||||||
/slw {setlinewidth} bind def
|
|
||||||
/srgb {setrgbcolor} bind def
|
|
||||||
/rot {rotate} bind def
|
|
||||||
/sc {scale} bind def
|
|
||||||
/sd {setdash} bind def
|
|
||||||
/ff {findfont} bind def
|
|
||||||
/sf {setfont} bind def
|
|
||||||
/scf {scalefont} bind def
|
|
||||||
/sw {stringwidth} bind def
|
|
||||||
/tr {translate} bind def
|
|
||||||
/tnt {dup dup currentrgbcolor
|
|
||||||
4 -2 roll dup 1 exch sub 3 -1 roll mul add
|
|
||||||
4 -2 roll dup 1 exch sub 3 -1 roll mul add
|
|
||||||
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
|
|
||||||
bind def
|
|
||||||
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
|
|
||||||
4 -2 roll mul srgb} bind def
|
|
||||||
/reencdict 12 dict def /ReEncode { reencdict begin
|
|
||||||
/newcodesandnames exch def /newfontname exch def /basefontname exch def
|
|
||||||
/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
|
|
||||||
basefontdict { exch dup /FID ne { dup /Encoding eq
|
|
||||||
{ exch dup length array copy newfont 3 1 roll put }
|
|
||||||
{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
|
|
||||||
newfont /FontName newfontname put newcodesandnames aload pop
|
|
||||||
128 1 255 { newfont /Encoding get exch /.notdef put } for
|
|
||||||
newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
|
|
||||||
newfontname newfont definefont pop end } def
|
|
||||||
/isovec [
|
|
||||||
8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
|
|
||||||
8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
|
|
||||||
8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
|
|
||||||
8#220 /dotlessi 8#230 /oe 8#231 /OE
|
|
||||||
8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
|
|
||||||
8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
|
|
||||||
8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
|
|
||||||
8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
|
|
||||||
8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
|
|
||||||
8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
|
|
||||||
8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
|
|
||||||
8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
|
|
||||||
8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
|
|
||||||
8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
|
|
||||||
8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
|
|
||||||
8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
|
|
||||||
8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
|
|
||||||
8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
|
|
||||||
8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
|
|
||||||
8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
|
|
||||||
8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
|
|
||||||
8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
|
|
||||||
8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
|
|
||||||
8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
|
|
||||||
8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
|
|
||||||
8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
|
|
||||||
/Times-Bold /Times-Bold-iso isovec ReEncode
|
|
||||||
/Times-Roman /Times-Roman-iso isovec ReEncode
|
|
||||||
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
|
|
||||||
/$F2psEnd {$F2psEnteredState restore end} def
|
|
||||||
|
|
||||||
/pageheader {
|
|
||||||
save
|
|
||||||
newpath 0 332 moveto 0 0 lineto 633 0 lineto 633 332 lineto closepath clip newpath
|
|
||||||
-331.7 473.8 translate
|
|
||||||
1 -1 scale
|
|
||||||
$F2psBegin
|
|
||||||
10 setmiterlimit
|
|
||||||
0 slj 0 slc
|
|
||||||
0.06000 0.06000 sc
|
|
||||||
} bind def
|
|
||||||
/pagefooter {
|
|
||||||
$F2psEnd
|
|
||||||
restore
|
|
||||||
} bind def
|
|
||||||
%%EndProlog
|
|
||||||
pageheader
|
|
||||||
%
|
|
||||||
% Fig objects follow
|
|
||||||
%
|
|
||||||
%
|
|
||||||
% here starts figure with depth 50
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
5925 7275 m
|
|
||||||
gs 1 -1 sc (Step 6: Client now knows that projection 12 is invalid. Fetch projection 13, then retry at step #8.) col16 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8550 3225 m
|
|
||||||
gs 1 -1 sc (Get epoch 13) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 6900 m
|
|
||||||
gs 1 -1 sc (Active=[a,b,c]) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 6675 m
|
|
||||||
gs 1 -1 sc (Members=[a,b,c]) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 6450 m
|
|
||||||
gs 1 -1 sc (Epoch=13) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 5580 m
|
|
||||||
gs 1 -1 sc (Epoch=12) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 5835 m
|
|
||||||
gs 1 -1 sc (Members=[a,b,c]) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 6090 m
|
|
||||||
gs 1 -1 sc (Active=[a,b]) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5925 5175 m
|
|
||||||
gs 1 -1 sc (Projection \(data structure\)) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
0 slj
|
|
||||||
0 slc
|
|
||||||
15.000 slw
|
|
||||||
n 8400 4950 m 5625 4950 l 5625 7050 l 8400 7050 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 6405 m
|
|
||||||
gs 1 -1 sc (- write once) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 6660 m
|
|
||||||
gs 1 -1 sc (- key=integer) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 6915 m
|
|
||||||
gs 1 -1 sc (- value=projection data structure) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 7170 m
|
|
||||||
gs 1 -1 sc (k=11, v=...) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 7425 m
|
|
||||||
gs 1 -1 sc (k=12, v=...) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 7680 m
|
|
||||||
gs 1 -1 sc (k=13, v=...) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 6150 m
|
|
||||||
gs 1 -1 sc (FLU projection store \(proc\)) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
n 12750 5925 m 15900 5925 l 15900 7725 l 12750 7725 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
% Polyline
|
|
||||||
gs clippath
|
|
||||||
14788 5055 m 14940 5055 l 14940 4995 l 14788 4995 l 14788 4995 l 14908 5025 l 14788 5055 l cp
|
|
||||||
14612 4995 m 14460 4995 l 14460 5055 l 14612 5055 l 14612 5055 l 14492 5025 l 14612 4995 l cp
|
|
||||||
eoclip
|
|
||||||
n 14475 5025 m
|
|
||||||
14925 5025 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 14612 4995 m 14492 5025 l 14612 5055 l col0 s
|
|
||||||
% arrowhead
|
|
||||||
n 14788 5055 m 14908 5025 l 14788 4995 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
15688 5055 m 15840 5055 l 15840 4995 l 15688 4995 l 15688 4995 l 15808 5025 l 15688 5055 l cp
|
|
||||||
15137 4995 m 14985 4995 l 14985 5055 l 15137 5055 l 15137 5055 l 15017 5025 l 15137 4995 l cp
|
|
||||||
eoclip
|
|
||||||
n 15000 5025 m
|
|
||||||
15825 5025 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 15137 4995 m 15017 5025 l 15137 5055 l col0 s
|
|
||||||
% arrowhead
|
|
||||||
n 15688 5055 m 15808 5025 l 15688 4995 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
14638 5355 m 14790 5355 l 14790 5295 l 14638 5295 l 14638 5295 l 14758 5325 l 14638 5355 l cp
|
|
||||||
14612 5295 m 14460 5295 l 14460 5355 l 14612 5355 l 14612 5355 l 14492 5325 l 14612 5295 l cp
|
|
||||||
eoclip
|
|
||||||
n 14475 5325 m 14550 5325 l 14625 5325 l 14700 5325 l 14775 5325 l 14700 5325 l
|
|
||||||
|
|
||||||
14775 5325 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 14612 5295 m 14492 5325 l 14612 5355 l col0 s
|
|
||||||
% arrowhead
|
|
||||||
n 14638 5355 m 14758 5325 l 14638 5295 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
15163 5355 m 15315 5355 l 15315 5295 l 15163 5295 l 15163 5295 l 15283 5325 l 15163 5355 l cp
|
|
||||||
15137 5295 m 14985 5295 l 14985 5355 l 15137 5355 l 15137 5355 l 15017 5325 l 15137 5295 l cp
|
|
||||||
eoclip
|
|
||||||
n 15000 5325 m 15075 5325 l 15150 5325 l 15225 5325 l
|
|
||||||
15300 5325 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 15137 5295 m 15017 5325 l 15137 5355 l col0 s
|
|
||||||
% arrowhead
|
|
||||||
n 15163 5355 m 15283 5325 l 15163 5295 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
15688 5355 m 15840 5355 l 15840 5295 l 15688 5295 l 15688 5295 l 15808 5325 l 15688 5355 l cp
|
|
||||||
15587 5295 m 15435 5295 l 15435 5355 l 15587 5355 l 15587 5355 l 15467 5325 l 15587 5295 l cp
|
|
||||||
eoclip
|
|
||||||
n 15450 5325 m 15525 5325 l 15600 5325 l 15675 5325 l 15750 5325 l
|
|
||||||
15825 5325 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 15587 5295 m 15467 5325 l 15587 5355 l col0 s
|
|
||||||
% arrowhead
|
|
||||||
n 15688 5355 m 15808 5325 l 15688 5295 l col0 s
|
|
||||||
% Polyline
|
|
||||||
[60] 0 sd
|
|
||||||
n 14475 5025 m
|
|
||||||
15825 5025 l gs col0 s gr [] 0 sd
|
|
||||||
% Polyline
|
|
||||||
[60] 0 sd
|
|
||||||
n 14475 5325 m
|
|
||||||
15825 5325 l gs col0 s gr [] 0 sd
|
|
||||||
% Polyline
|
|
||||||
[60] 0 sd
|
|
||||||
n 14475 5550 m
|
|
||||||
15825 5550 l gs col0 s gr [] 0 sd
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 4575 m
|
|
||||||
gs 1 -1 sc (epoch=13) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 4830 m
|
|
||||||
gs 1 -1 sc (files:) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 5085 m
|
|
||||||
gs 1 -1 sc ( "foo.seq_a.006") col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 5340 m
|
|
||||||
gs 1 -1 sc ( "foo.seq_b.007") col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 5595 m
|
|
||||||
gs 1 -1 sc ( "foo.seq_b.008") col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 4275 m
|
|
||||||
gs 1 -1 sc (FLU \(proc\)) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
n 12750 4050 m 15975 4050 l 15975 5775 l 12750 5775 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
% Polyline
|
|
||||||
n 12750 2775 m 15150 2775 l 15150 3900 l 12750 3900 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 3000 m
|
|
||||||
gs 1 -1 sc (Sequencer \(proc\)) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 3300 m
|
|
||||||
gs 1 -1 sc (epoch=13) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
12825 3555 m
|
|
||||||
gs 1 -1 sc (map=[{"foo", next_file=8,) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
13500 3750 m
|
|
||||||
gs 1 -1 sc (next_offset=0}...]) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
n 5700 3975 m 5700 4275 l 8250 4275 l 8250 3075 l 7950 3075 l 7950 3975 l
|
|
||||||
|
|
||||||
5700 3975 l cp gs col0 s gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5775 4200 m
|
|
||||||
gs 1 -1 sc (server logic) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5775 3060 m
|
|
||||||
gs 1 -1 sc (Append <<123 bytes>>) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5775 3315 m
|
|
||||||
gs 1 -1 sc (to a file with prefix) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5775 3570 m
|
|
||||||
gs 1 -1 sc ("foo".) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
5775 2700 m
|
|
||||||
gs 1 -1 sc (CLIENT \(proc\)) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
gs clippath
|
|
||||||
5970 3763 m 5970 3915 l 6030 3915 l 6030 3763 l 6030 3763 l 6000 3883 l 5970 3763 l cp
|
|
||||||
eoclip
|
|
||||||
n 6000 3600 m
|
|
||||||
6000 3900 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 5970 3763 m 6000 3883 l 6030 3763 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
6630 3737 m 6630 3585 l 6570 3585 l 6570 3737 l 6570 3737 l 6600 3617 l 6630 3737 l cp
|
|
||||||
eoclip
|
|
||||||
n 6600 3900 m 6600 3825 l 6600 3750 l 6600 3675 l
|
|
||||||
6600 3600 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 6630 3737 m 6600 3617 l 6570 3737 l col0 s
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
6675 3900 m
|
|
||||||
gs 1 -1 sc (ok) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
n 5550 4350 m 8325 4350 l 8325 2475 l 5550 2475 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
% Polyline
|
|
||||||
gs clippath
|
|
||||||
8143 4500 m 8035 4393 l 7993 4435 l 8100 4543 l 8100 4543 l 8037 4437 l 8143 4500 l cp
|
|
||||||
eoclip
|
|
||||||
n 12525 5175 m 8775 5175 l
|
|
||||||
8025 4425 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 8143 4500 m 8037 4437 l 8100 4543 l col0 s
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
11625 5100 m
|
|
||||||
gs 1 -1 sc (ok) col0 sh gr
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
5970 4663 m 5970 4815 l 6030 4815 l 6030 4663 l 6030 4663 l 6000 4783 l 5970 4663 l cp
|
|
||||||
eoclip
|
|
||||||
n 6000 4425 m
|
|
||||||
6000 4800 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 5970 4663 m 6000 4783 l 6030 4663 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
6630 4562 m 6630 4410 l 6570 4410 l 6570 4562 l 6570 4562 l 6600 4442 l 6630 4562 l cp
|
|
||||||
eoclip
|
|
||||||
n 6600 4800 m 6600 4650 l 6600 4575 l 6600 4500 l
|
|
||||||
6600 4425 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 6630 4562 m 6600 4442 l 6570 4562 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
12388 2730 m 12540 2730 l 12540 2670 l 12388 2670 l 12388 2670 l 12508 2700 l 12388 2730 l cp
|
|
||||||
eoclip
|
|
||||||
n 8475 2700 m
|
|
||||||
12525 2700 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 12388 2730 m 12508 2700 l 12388 2670 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
8612 2970 m 8460 2970 l 8460 3030 l 8612 3030 l 8612 3030 l 8492 3000 l 8612 2970 l cp
|
|
||||||
eoclip
|
|
||||||
n 12525 3000 m
|
|
||||||
8475 3000 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 8612 2970 m 8492 3000 l 8612 3030 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
8612 3645 m 8460 3645 l 8460 3705 l 8612 3705 l 8612 3705 l 8492 3675 l 8612 3645 l cp
|
|
||||||
eoclip
|
|
||||||
n 12525 6900 m 12000 6900 l 12000 3675 l
|
|
||||||
8475 3675 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 8612 3645 m 8492 3675 l 8612 3705 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
12388 3330 m 12540 3330 l 12540 3270 l 12388 3270 l 12388 3270 l 12508 3300 l 12388 3330 l cp
|
|
||||||
eoclip
|
|
||||||
n 8475 3975 m 12300 3975 l 12300 3300 l
|
|
||||||
12525 3300 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 12388 3330 m 12508 3300 l 12388 3270 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
12388 4905 m 12540 4905 l 12540 4845 l 12388 4845 l 12388 4845 l 12508 4875 l 12388 4905 l cp
|
|
||||||
eoclip
|
|
||||||
n 8250 4425 m 8700 4875 l
|
|
||||||
12525 4875 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 12388 4905 m 12508 4875 l 12388 4845 l col0 s
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
n 12675 2400 m 16050 2400 l 16050 7875 l 12675 7875 l
|
|
||||||
cp gs col0 s gr
|
|
||||||
% Polyline
|
|
||||||
gs clippath
|
|
||||||
8612 4245 m 8460 4245 l 8460 4305 l 8612 4305 l 8612 4305 l 8492 4275 l 8612 4245 l cp
|
|
||||||
eoclip
|
|
||||||
n 12525 3600 m 12375 3600 l 12375 4275 l
|
|
||||||
8475 4275 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 8612 4245 m 8492 4275 l 8612 4305 l col0 s
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8850 5625 m
|
|
||||||
gs 1 -1 sc (Write to FLU B -> ok) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8850 6135 m
|
|
||||||
gs 1 -1 sc (Write to FLU C -> ok) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8550 2625 m
|
|
||||||
gs 1 -1 sc (Request 123 bytes, prefix="foo", epoch=12) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
11100 2925 m
|
|
||||||
gs 1 -1 sc ({bad_epoch,13}) col4 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
10875 3600 m
|
|
||||||
gs 1 -1 sc ({ok, proj=...}) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8550 4500 m
|
|
||||||
gs 1 -1 sc (Write <<123 bytes>> to) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8550 4755 m
|
|
||||||
gs 1 -1 sc (file="foo.seq_a.008", offset=0) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
13575 2625 m
|
|
||||||
gs 1 -1 sc (Server A) col0 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
8550 3900 m
|
|
||||||
gs 1 -1 sc (Req. 123 bytes, prefix="foo", epoch=13) col0 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
6075 3825 m
|
|
||||||
gs 1 -1 sc (1) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
6075 4650 m
|
|
||||||
gs 1 -1 sc (2) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
6675 4650 m
|
|
||||||
gs 1 -1 sc (3) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
10950 2850 m
|
|
||||||
gs 1 -1 sc (5) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
10725 3525 m
|
|
||||||
gs 1 -1 sc (7) col16 sh gr
|
|
||||||
/Times-Bold-iso ff 200.00 scf sf
|
|
||||||
9375 4200 m
|
|
||||||
gs 1 -1 sc (file="foo.seq_a.008", offset=0) col0 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8400 3225 m
|
|
||||||
gs 1 -1 sc (6) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8400 2625 m
|
|
||||||
gs 1 -1 sc (4) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
6675 3750 m
|
|
||||||
gs 1 -1 sc (16) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8400 3900 m
|
|
||||||
gs 1 -1 sc (8) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
9225 4200 m
|
|
||||||
gs 1 -1 sc (9) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8400 4500 m
|
|
||||||
gs 1 -1 sc (10) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8475 5625 m
|
|
||||||
gs 1 -1 sc (12,13) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
8475 6075 m
|
|
||||||
gs 1 -1 sc (14,15) col16 sh gr
|
|
||||||
/Times-Roman-iso ff 166.67 scf sf
|
|
||||||
11400 5100 m
|
|
||||||
gs 1 -1 sc (11) col16 sh gr
|
|
||||||
% Polyline
|
|
||||||
15.000 slw
|
|
||||||
gs clippath
|
|
||||||
12388 6630 m 12540 6630 l 12540 6570 l 12388 6570 l 12388 6570 l 12508 6600 l 12388 6630 l cp
|
|
||||||
eoclip
|
|
||||||
n 8475 3300 m 12150 3300 l 12150 6600 l
|
|
||||||
12525 6600 l gs col0 s gr gr
|
|
||||||
|
|
||||||
% arrowhead
|
|
||||||
7.500 slw
|
|
||||||
n 12388 6630 m 12508 6600 l 12388 6570 l col0 s
|
|
||||||
% here ends figure;
|
|
||||||
pagefooter
|
|
||||||
showpage
|
|
||||||
%%Trailer
|
|
||||||
%EOF
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,145 +0,0 @@
|
||||||
%!PS-Adobe-3.0 EPSF-2.0
|
|
||||||
%%BoundingBox: 0 0 420.000000 166.599991
|
|
||||||
%%Creator: mscgen 0.18
|
|
||||||
%%EndComments
|
|
||||||
0.700000 0.700000 scale
|
|
||||||
0 0 moveto
|
|
||||||
0 238 lineto
|
|
||||||
600 238 lineto
|
|
||||||
600 0 lineto
|
|
||||||
closepath
|
|
||||||
clip
|
|
||||||
%PageTrailer
|
|
||||||
%Page: 1 1
|
|
||||||
/Helvetica findfont
|
|
||||||
10 scalefont
|
|
||||||
setfont
|
|
||||||
/Helvetica findfont
|
|
||||||
12 scalefont
|
|
||||||
setfont
|
|
||||||
0 238 translate
|
|
||||||
/mtrx matrix def
|
|
||||||
/ellipse
|
|
||||||
{ /endangle exch def
|
|
||||||
/startangle exch def
|
|
||||||
/ydia exch def
|
|
||||||
/xdia exch def
|
|
||||||
/y exch def
|
|
||||||
/x exch def
|
|
||||||
/savematrix mtrx currentmatrix def
|
|
||||||
x y translate
|
|
||||||
xdia 2 div ydia 2 div scale
|
|
||||||
1 -1 scale
|
|
||||||
0 0 1 startangle endangle arc
|
|
||||||
savematrix setmatrix
|
|
||||||
} def
|
|
||||||
(client) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 75 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
75 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(Projection) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 225 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
225 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(ProjStore_C) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 375 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
375 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
(FLU_C) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup dup newpath 525 -17 moveto 2 div neg 0 rmoveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
525 -15 moveto dup stringwidth pop 2 div neg 0 rmoveto show
|
|
||||||
newpath 75 -22 moveto 75 -49 lineto stroke
|
|
||||||
newpath 225 -22 moveto 225 -49 lineto stroke
|
|
||||||
newpath 375 -22 moveto 375 -49 lineto stroke
|
|
||||||
newpath 525 -22 moveto 525 -49 lineto stroke
|
|
||||||
newpath 75 -35 moveto 225 -35 lineto stroke
|
|
||||||
newpath 225 -35 moveto 215 -41 lineto stroke
|
|
||||||
(get current) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 122 -33 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
122 -33 moveto show
|
|
||||||
newpath 75 -49 moveto 75 -76 lineto stroke
|
|
||||||
newpath 225 -49 moveto 225 -76 lineto stroke
|
|
||||||
newpath 375 -49 moveto 375 -76 lineto stroke
|
|
||||||
newpath 525 -49 moveto 525 -76 lineto stroke
|
|
||||||
newpath 225 -62 moveto 75 -62 lineto stroke
|
|
||||||
newpath 75 -62 moveto 85 -68 lineto stroke
|
|
||||||
(ok, #12...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 126 -60 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
126 -60 moveto show
|
|
||||||
newpath 75 -76 moveto 75 -103 lineto stroke
|
|
||||||
newpath 225 -76 moveto 225 -103 lineto stroke
|
|
||||||
newpath 375 -76 moveto 375 -103 lineto stroke
|
|
||||||
newpath 525 -76 moveto 525 -103 lineto stroke
|
|
||||||
newpath 75 -89 moveto 525 -89 lineto stroke
|
|
||||||
newpath 525 -89 moveto 515 -95 lineto stroke
|
|
||||||
(read "foo.seq_a.009" offset=447 bytes=123 epoch=12) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 157 -87 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
157 -87 moveto show
|
|
||||||
newpath 75 -103 moveto 75 -130 lineto stroke
|
|
||||||
newpath 225 -103 moveto 225 -130 lineto stroke
|
|
||||||
newpath 375 -103 moveto 375 -130 lineto stroke
|
|
||||||
newpath 525 -103 moveto 525 -130 lineto stroke
|
|
||||||
newpath 525 -116 moveto 75 -116 lineto stroke
|
|
||||||
newpath 75 -116 moveto 85 -122 lineto stroke
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
(bad_epoch, 13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 261 -114 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
1.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
261 -114 moveto show
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
newpath 75 -130 moveto 75 -157 lineto stroke
|
|
||||||
newpath 225 -130 moveto 225 -157 lineto stroke
|
|
||||||
newpath 375 -130 moveto 375 -157 lineto stroke
|
|
||||||
newpath 525 -130 moveto 525 -157 lineto stroke
|
|
||||||
newpath 75 -143 moveto 375 -143 lineto stroke
|
|
||||||
newpath 375 -143 moveto 365 -149 lineto stroke
|
|
||||||
(get epoch #13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 187 -141 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
187 -141 moveto show
|
|
||||||
newpath 75 -157 moveto 75 -184 lineto stroke
|
|
||||||
newpath 225 -157 moveto 225 -184 lineto stroke
|
|
||||||
newpath 375 -157 moveto 375 -184 lineto stroke
|
|
||||||
newpath 525 -157 moveto 525 -184 lineto stroke
|
|
||||||
newpath 375 -170 moveto 75 -170 lineto stroke
|
|
||||||
newpath 75 -170 moveto 85 -176 lineto stroke
|
|
||||||
(ok, #13...) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 201 -168 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
201 -168 moveto show
|
|
||||||
newpath 75 -184 moveto 75 -211 lineto stroke
|
|
||||||
newpath 225 -184 moveto 225 -211 lineto stroke
|
|
||||||
newpath 375 -184 moveto 375 -211 lineto stroke
|
|
||||||
newpath 525 -184 moveto 525 -211 lineto stroke
|
|
||||||
newpath 75 -197 moveto 525 -197 lineto stroke
|
|
||||||
newpath 525 -197 moveto 515 -203 lineto stroke
|
|
||||||
(read "foo.seq_a.009" offset=447 bytes=123 epoch=13) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 157 -195 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
157 -195 moveto show
|
|
||||||
newpath 75 -211 moveto 75 -238 lineto stroke
|
|
||||||
newpath 225 -211 moveto 225 -238 lineto stroke
|
|
||||||
newpath 375 -211 moveto 375 -238 lineto stroke
|
|
||||||
newpath 525 -211 moveto 525 -238 lineto stroke
|
|
||||||
newpath 525 -224 moveto 75 -224 lineto stroke
|
|
||||||
newpath 75 -224 moveto 85 -230 lineto stroke
|
|
||||||
(ok, <<...123...>>) dup stringwidth
|
|
||||||
1.000000 1.000000 1.000000 setrgbcolor
|
|
||||||
pop dup newpath 257 -222 moveto 0 rlineto 0 11 rlineto neg 0 rlineto closepath fill
|
|
||||||
0.000000 0.000000 0.000000 setrgbcolor
|
|
||||||
257 -222 moveto show
|
|
File diff suppressed because it is too large
Load diff
2
ebin/.gitignore
vendored
2
ebin/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
*.beam
|
|
||||||
*.app
|
|
1
edoc/.gitignore
vendored
Normal file
1
edoc/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
tmp.*
|
13
edoc/edoc-info
Normal file
13
edoc/edoc-info
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
%% encoding: UTF-8
|
||||||
|
{application,machi}.
|
||||||
|
{packages,[]}.
|
||||||
|
{modules,[machi_admin_util,machi_app,machi_basho_bench_driver,
|
||||||
|
machi_chain_manager1,machi_chain_repair,machi_chash,machi_cinfo,
|
||||||
|
machi_config,machi_cr_client,machi_csum_table,machi_dt,
|
||||||
|
machi_file_proxy,machi_file_proxy_sup,machi_fitness,machi_flu1,
|
||||||
|
machi_flu1_client,machi_flu_filename_mgr,machi_flu_metadata_mgr,
|
||||||
|
machi_flu_metadata_mgr_sup,machi_flu_psup,machi_flu_sup,
|
||||||
|
machi_lifecycle_mgr,machi_merkle_tree,machi_pb_high_client,
|
||||||
|
machi_pb_translate,machi_plist,machi_projection,
|
||||||
|
machi_projection_store,machi_proxy_flu1_client,machi_sup,machi_util,
|
||||||
|
machi_yessir_client]}.
|
BIN
edoc/erlang.png
Normal file
BIN
edoc/erlang.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
17
edoc/index.html
Normal file
17
edoc/index.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The machi application</title>
|
||||||
|
</head>
|
||||||
|
<frameset cols="20%,80%">
|
||||||
|
<frame src="modules-frame.html" name="modulesFrame" title="">
|
||||||
|
|
||||||
|
<frame src="overview-summary.html" name="overviewFrame" title="">
|
||||||
|
<noframes>
|
||||||
|
<h2>This page uses frames</h2>
|
||||||
|
<p>Your browser does not accept frames.
|
||||||
|
<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead.
|
||||||
|
</p>
|
||||||
|
</noframes>
|
||||||
|
</frameset>
|
||||||
|
</html>
|
50
edoc/machi_admin_util.html
Normal file
50
edoc/machi_admin_util.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_admin_util</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_admin_util</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Machi chain replication administration utilities.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>Machi chain replication administration utilities.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#verify_file_checksums_local-3">verify_file_checksums_local/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#verify_file_checksums_local-4">verify_file_checksums_local/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#verify_file_checksums_remote-3">verify_file_checksums_remote/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#verify_file_checksums_remote-4">verify_file_checksums_remote/4</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verify_file_checksums_local-3">verify_file_checksums_local/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verify_file_checksums_local(Sock1::port(), EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Path::binary() | list()) -> {ok, [tuple()]} | {error, term()}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verify_file_checksums_local-4">verify_file_checksums_local/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verify_file_checksums_local(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Path::binary() | list()) -> {ok, [tuple()]} | {error, term()}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verify_file_checksums_remote-3">verify_file_checksums_remote/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verify_file_checksums_remote(Sock1::port(), EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::binary() | list()) -> {ok, [tuple()]} | {error, term()}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verify_file_checksums_remote-4">verify_file_checksums_remote/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verify_file_checksums_remote(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::binary() | list()) -> {ok, [tuple()]} | {error, term()}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
42
edoc/machi_app.html
Normal file
42
edoc/machi_app.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_app</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_app</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Start the top-level supervisor for the Machi application.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="application.html"><tt>application</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Start the top-level supervisor for the Machi application.</p>
|
||||||
|
|
||||||
|
See <a href="machi_flu_psup.html"><code>machi_flu_psup</code></a> for an illustration of the entire Machi
|
||||||
|
application process structure.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start-2">start/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start(StartType, StartArgs) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop-1">stop/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop(State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
64
edoc/machi_basho_bench_driver.html
Normal file
64
edoc/machi_basho_bench_driver.html
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_basho_bench_driver</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_basho_bench_driver</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>A simple basho_bench driver for Machi.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>A simple basho_bench driver for Machi</p>
|
||||||
|
|
||||||
|
<p>Basho_bench was originally developed to stress test key-value
|
||||||
|
stores (as was YCSB and several other mechmarking tools). A person
|
||||||
|
can consider the UNIX file system to be a key-value store and thus
|
||||||
|
use basho_bench to measure its performance under a certain
|
||||||
|
workload. Machi is a bit different than most KV stores in that the
|
||||||
|
client has no direct control over the keys -- Machi servers always
|
||||||
|
assign the keys. The schemes typically used by basho_bench & YCSB
|
||||||
|
to use/mimic key naming conventions used internally ... are
|
||||||
|
difficult to adapt to Machi.</p>
|
||||||
|
|
||||||
|
<p>So, we'll try to manage key reading by using a common ETS table
|
||||||
|
that is populated with:</p>
|
||||||
|
|
||||||
|
<p>1. Key: <code>non_neg_integer()`
|
||||||
|
2. Value: The `{File,Offset,Size}` for a chunk previously written.
|
||||||
|
|
||||||
|
At startup time, basho_bench can use the `list_files</code> and
|
||||||
|
<code>checksum_list</code> API operations to fetch all of the
|
||||||
|
<code>{File,Offset,Size}` tuples that currently reside in the cluster.
|
||||||
|
Also, optionally (?), each new `append</code> operation by the b_b driver
|
||||||
|
could add new entries to this ETS table.</p>
|
||||||
|
|
||||||
|
Now we can use various integer-centric key generators that are
|
||||||
|
already bundled with basho_bench.
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#new-1">new/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#run-4">run/4</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="new-1">new/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>new(Id) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="run-4">run/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>run(X1, KeyGen, ValueGen, M) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
289
edoc/machi_chain_manager1.html
Normal file
289
edoc/machi_chain_manager1.html
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_chain_manager1</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_chain_manager1</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The Machi chain manager, Guardian of all things related to
|
||||||
|
Chain Replication state, status, and data replica safety.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>The Machi chain manager, Guardian of all things related to
|
||||||
|
Chain Replication state, status, and data replica safety.</p>
|
||||||
|
|
||||||
|
<p>The Chain Manager is responsible for managing the state of Machi's
|
||||||
|
"Chain Replication" state. This role is roughly analogous to the
|
||||||
|
"Riak Core" application inside of Riak, which takes care of
|
||||||
|
coordinating replica placement and replica repair.</p>
|
||||||
|
|
||||||
|
<p>For each primitive data server in the cluster, a Machi FLU, there
|
||||||
|
is a Chain Manager process that manages its FLU's role within the
|
||||||
|
Machi cluster's Chain Replication scheme. Each Chain Manager
|
||||||
|
process executes locally and independently to manage the
|
||||||
|
distributed state of a single Machi Chain Replication chain.</p>
|
||||||
|
|
||||||
|
Machi's Chain Manager process performs similar tasks as Riak Core's
|
||||||
|
claimant. However, Machi has several active Chain Manager
|
||||||
|
processes, one per FLU server, instead of a single active process
|
||||||
|
like Core's claimant. Each Chain Manager process acts
|
||||||
|
independently; each is constrained so that it will reach consensus
|
||||||
|
via independent computation & action.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#chain_state_transition_is_sane-6">chain_state_transition_is_sane/6</a></td><td>Check if a projection transition is sane & safe: we assume
|
||||||
|
that the caller has checked basic projection data structure contents.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#format_status-2">format_status/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_ps-2">get_ps/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_remember_down_list-0">get_remember_down_list/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#has_not_sane-2">has_not_sane/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init_remember_down_list-0">init_remember_down_list/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_chmgr_regname-1">make_chmgr_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#mk-3">mk/3</a></td><td>Create a 2-tuple that describes how <code>UPI1</code> + <code>Repair1</code> are
|
||||||
|
transformed into <code>UPI2</code> in a chain state change.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#perhaps_call-5">perhaps_call/5</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#ping-1">ping/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#projection_transitions_are_sane-2">projection_transitions_are_sane/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#scan_dir-4">scan_dir/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#set_active-2">set_active/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#set_chain_members-2">set_chain_members/2</a></td><td>Set chain members list.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#set_chain_members-6">set_chain_members/6</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#simple_chain_state_transition_is_sane-3">simple_chain_state_transition_is_sane/3</a></td><td>A simple technique for checking chain state transition safety.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#simple_chain_state_transition_is_sane-5">simple_chain_state_transition_is_sane/5</a></td><td>Simple check if a projection transition is sane & safe: we assume
|
||||||
|
that the caller has checked basic projection data structure contents.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-3">start_link/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#strip_dbg2-1">strip_dbg2/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#test_calc_projection-2">test_calc_projection/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#test_read_latest_public_projection-2">test_read_latest_public_projection/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#test_write_public_projection-2">test_write_public_projection/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trigger_react_to_env-1">trigger_react_to_env/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#update_remember_down_list-1">update_remember_down_list/1</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="chain_state_transition_is_sane-6">chain_state_transition_is_sane/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>chain_state_transition_is_sane(Author1, UPI1, Repair1, Author2, UPI2, RelativeToServer) -> any()</tt></p>
|
||||||
|
</div><p><p>Check if a projection transition is sane & safe: we assume
|
||||||
|
that the caller has checked basic projection data structure contents.</p>
|
||||||
|
|
||||||
|
NOTE: The return value convention is <code>true</code> for sane/safe and <code>term() /=
|
||||||
|
true</code> for any unsafe/insane value. This function (and its callee
|
||||||
|
functions) are the only functions (throughout all of the chain state
|
||||||
|
transition sanity checking functions) that is allowed to return <code>false</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="format_status-2">format_status/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>format_status(Opt, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_ps-2">get_ps/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_ps(Projection_v1, Acc) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_remember_down_list-0">get_remember_down_list/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_remember_down_list() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Call, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Cast, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Msg, Ch_mgr) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="has_not_sane-2">has_not_sane/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>has_not_sane(Projection_v1, Acc) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init_remember_down_list-0">init_remember_down_list/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init_remember_down_list() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_chmgr_regname-1">make_chmgr_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_chmgr_regname(A) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="mk-3">mk/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>mk(UPI1, Repair1, UPI2) -> any()</tt></p>
|
||||||
|
</div><p><p>Create a 2-tuple that describes how <code>UPI1</code> + <code>Repair1</code> are
|
||||||
|
transformed into <code>UPI2</code> in a chain state change.</p>
|
||||||
|
|
||||||
|
<p>The 1st part of the 2-tuple is a list of <code>keep</code> and <code>del</code> instructions,
|
||||||
|
relative to the items in UPI1 and whether they are present (<code>keep</code>) or
|
||||||
|
absent (<code>del</code>) in <code>UPI2</code>.</p>
|
||||||
|
|
||||||
|
The 2nd part of the 2-tuple is <code>list(non_neg_integer()|error)</code> that
|
||||||
|
describes the relative order of items in <code>Repair1</code> that appear in
|
||||||
|
<code>UPI2</code>. The <code>error</code> atom is used to denote items not present in
|
||||||
|
<code>Repair1</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="perhaps_call-5">perhaps_call/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>perhaps_call(ProxyPid, MyName, Partitions, FLU, DoIt) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="ping-1">ping/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>ping(Pid) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="projection_transitions_are_sane-2">projection_transitions_are_sane/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>projection_transitions_are_sane(Ps, RelativeToServer) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="scan_dir-4">scan_dir/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>scan_dir(Dir, FileFilterFun, FoldEachFun, FoldEachAcc) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="set_active-2">set_active/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>set_active(Pid, Boolean) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="set_chain_members-2">set_chain_members/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>set_chain_members(Pid, MembersDict) -> any()</tt></p>
|
||||||
|
</div><p><p>Set chain members list.</p>
|
||||||
|
|
||||||
|
NOTE: This implementation is a bit brittle, in that an author with
|
||||||
|
higher rank may try to re-suggest the old membership list if it
|
||||||
|
races with an author of lower rank. For now, we suggest calling
|
||||||
|
set_chain_members() first on the author of highest rank and finish
|
||||||
|
with lowest rank, i.e. name z* first, name a* last.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="set_chain_members-6">set_chain_members/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>set_chain_members(Pid, ChainName, OldEpoch, CMode, MembersDict, Witness_list) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="simple_chain_state_transition_is_sane-3">simple_chain_state_transition_is_sane/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>simple_chain_state_transition_is_sane(UPI1, Repair1, UPI2) -> any()</tt></p>
|
||||||
|
</div><p><p>A simple technique for checking chain state transition safety.</p>
|
||||||
|
|
||||||
|
<p>Math tells us that any change state <code>UPI1</code> plus <code>Repair1</code> to state
|
||||||
|
<code>UPI2</code> is OK as long as <code>UPI2</code> is a concatenation of some
|
||||||
|
order-preserving combination from <code>UPI1</code> with some order-preserving
|
||||||
|
combination from <code>Repair1</code>.</p>
|
||||||
|
|
||||||
|
<pre> Good_UPI2s = [ X ++ Y || X <- machi_util:ordered_combinations(UPI1),
|
||||||
|
Y <- machi_util:ordered_combinations(Repair1)]</pre>
|
||||||
|
|
||||||
|
<p>Rather than creating that list and then checking if <code>UPI2</code> is in
|
||||||
|
it, we try a <code>diff</code>-like technique to check for basic state
|
||||||
|
transition safety. See docs for <a href="#mk-3"><code>mk/3</code></a> for more detail.</p>
|
||||||
|
|
||||||
|
<pre> 2> machi_chain_manager1:mk([a,b], [], [a]).
|
||||||
|
{[keep,del],[]} %% good transition
|
||||||
|
3> machi_chain_manager1:mk([a,b], [], [b,a]).
|
||||||
|
{[del,keep],[]} %% bad transition: too few 'keep' for UPI2's length 2
|
||||||
|
4> machi_chain_manager1:mk([a,b], [c,d,e], [a,d]).
|
||||||
|
{[keep,del],[2]} %% good transition
|
||||||
|
5> machi_chain_manager1:mk([a,b], [c,d,e], [a,bogus]).
|
||||||
|
{[keep,del],[error]} %% bad transition: 'bogus' not in Repair1</pre></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="simple_chain_state_transition_is_sane-5">simple_chain_state_transition_is_sane/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>simple_chain_state_transition_is_sane(Author1, UPI1, Repair1, Author2, UPI2) -> any()</tt></p>
|
||||||
|
</div><p><p>Simple check if a projection transition is sane & safe: we assume
|
||||||
|
that the caller has checked basic projection data structure contents.</p>
|
||||||
|
|
||||||
|
NOTE: The return value convention is <code>true</code> for sane/safe and
|
||||||
|
<code>term() /= true</code> for any unsafe/insane value.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-2">start_link/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(MyName, MembersDict) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-3">start_link/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(MyName, MembersDict, MgrOpts) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop-1">stop/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop(Pid) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="strip_dbg2-1">strip_dbg2/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>strip_dbg2(P) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="test_calc_projection-2">test_calc_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>test_calc_projection(Pid, KeepRunenvP) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="test_read_latest_public_projection-2">test_read_latest_public_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>test_read_latest_public_projection(Pid, ReadRepairP) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="test_write_public_projection-2">test_write_public_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>test_write_public_projection(Pid, Proj) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trigger_react_to_env-1">trigger_react_to_env/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trigger_react_to_env(Pid) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="update_remember_down_list-1">update_remember_down_list/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>update_remember_down_list(FLU) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
91
edoc/machi_chain_repair.html
Normal file
91
edoc/machi_chain_repair.html
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_chain_repair</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_chain_repair</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Perform "chain repair", i.e., resynchronization of Machi file
|
||||||
|
contents and metadata as servers are (re-)added to the chain.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Perform "chain repair", i.e., resynchronization of Machi file
|
||||||
|
contents and metadata as servers are (re-)added to the chain.</p>
|
||||||
|
|
||||||
|
<p>The implementation here is a very basic one, and is probably a bit
|
||||||
|
slower than the original "demo day" implementation at
|
||||||
|
<a href="https://github.com/basho/machi/blob/master/prototype/demo-day-hack/file0_repair_server.escript" target="_top"><tt>https://github.com/basho/machi/blob/master/prototype/demo-day-hack/file0_repair_server.escript</tt></a></p>
|
||||||
|
|
||||||
|
<p>It's so easy to bikeshed this into a 1 year programming exercise.</p>
|
||||||
|
|
||||||
|
<p>General TODO note: There are a lot of areas for exploiting parallelism here.
|
||||||
|
I've set the bikeshed aside for now, but "make repair faster" has a
|
||||||
|
lot of room for exploiting concurrency, overlapping reads & writes,
|
||||||
|
etc etc. There are also lots of different trade-offs to make with
|
||||||
|
regard to RAM use vs. disk use.</p>
|
||||||
|
|
||||||
|
<p>There's no reason why repair can't be done:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li> Repair in parallel across multiple repairees ... Optimization.
|
||||||
|
</li>
|
||||||
|
<li> Repair multiple byte ranges concurrently ... Optimization.
|
||||||
|
</li>
|
||||||
|
<li><p> Use bigger chunks than the client originally used to write the file
|
||||||
|
... Optimization ... but it would be the easiest to implement, e.g. use
|
||||||
|
constant-sized 4MB chunks. Unfortuntely, it would also destroy
|
||||||
|
the ability to verify here that the chunk checksums are correct
|
||||||
|
*and* also propagate the correct checksum metadata to the
|
||||||
|
destination FLU.</p>
|
||||||
|
|
||||||
|
As an additional optimization, add a bit of #2 to start the next
|
||||||
|
read while the current write is still in progress.
|
||||||
|
</li>
|
||||||
|
<li> The current method centralizes the "smarts" required to compare
|
||||||
|
checksum differences ... move some computation to each FLU, then use
|
||||||
|
a Merkle- or other-compression-style scheme to reduce the amount of
|
||||||
|
data sent across a network.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>Most/all of this could be executed in parallel on each FLU relative to
|
||||||
|
its own files. Then, in another TODO option, perhaps build a Merkle tree
|
||||||
|
or other summary of the local files and send that data structure to the
|
||||||
|
repair coordinator.</p>
|
||||||
|
|
||||||
|
<p>Also, as another TODO note, repair_both_present() in the
|
||||||
|
prototype/demo-day code uses an optimization of calculating the MD5
|
||||||
|
checksum of the chunk checksum data as it arrives, and if the two MD5s
|
||||||
|
match, then we consider the two files in sync. If there isn't a match,
|
||||||
|
then we sort the lines and try another MD5, and if they match, then we're
|
||||||
|
in sync. In theory, that's lower overhead than the procedure used here.</p>
|
||||||
|
|
||||||
|
NOTE that one reason I chose the "directives list" method is to have an
|
||||||
|
option, later, of choosing to repair a subset of repairee FLUs if there
|
||||||
|
is a big discrepency between out of sync files: e.g., if FLU x has N
|
||||||
|
bytes out of sync but FLU y has 50N bytes out of sync, then it's likely
|
||||||
|
better to repair x only so that x can return to the UPI list quickly.
|
||||||
|
Also, in the event that all repairees are roughly comparably out of sync,
|
||||||
|
then the repair network traffic can be minimized by reading each chunk
|
||||||
|
only once.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#repair-7">repair/7</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="repair-7">repair/7</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>repair(ConsistencyMode, Src, Repairing, UPI, MembersDict, ETS, Opts) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
171
edoc/machi_chash.html
Normal file
171
edoc/machi_chash.html
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_chash</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_chash</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Consistent hashing library.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Consistent hashing library. Also known as "random slicing".</p>
|
||||||
|
|
||||||
|
This code was originally from the Hibari DB source code at
|
||||||
|
<a href="https://github.com/hibari" target="_top"><tt>https://github.com/hibari</tt></a>
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-float_map">float_map()</a></h3>
|
||||||
|
<p><tt>float_map() = [{<a href="#type-owner_name">owner_name()</a>, float()}]</tt></p>
|
||||||
|
<p> A float map subdivides the unit interval, starting at 0.0, to
|
||||||
|
partitions that are assigned to various owners. The sum of all
|
||||||
|
floats must be exactly 1.0 (or close enough for floating point
|
||||||
|
purposes).</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-float_tree">float_tree()</a></h3>
|
||||||
|
<p><b>abstract datatype</b>: <tt>float_tree()</tt></p>
|
||||||
|
<p> We can't use gb_trees:tree() because 'nil' (the empty tree) is
|
||||||
|
never valid in our case. But teaching Dialyzer that is difficult.</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-nextfloat_list">nextfloat_list()</a></h3>
|
||||||
|
<p><tt>nextfloat_list() = [{float(), <a href="#type-brick">brick()</a>}]</tt></p>
|
||||||
|
<p>A nextfloat_list
|
||||||
|
differs from a float_map in two respects: 1) nextfloat_list contains
|
||||||
|
tuples with the brick name in 2nd position, 2) the float() at each
|
||||||
|
position I_n > I_m, for all n, m such that n > m.
|
||||||
|
For example, a nextfloat_list of the float_map example above,
|
||||||
|
[{0.25, {br1, nd1}}, {0.75, {br2, nd1}}, {1.0, {br3, nd1}].</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-owner_int_range">owner_int_range()</a></h3>
|
||||||
|
<p><tt>owner_int_range() = {<a href="#type-owner_name">owner_name()</a>, non_neg_integer(), non_neg_integer()}</tt></p>
|
||||||
|
<p> Used when "prettying" a float map.</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-owner_name">owner_name()</a></h3>
|
||||||
|
<p><tt>owner_name() = term()</tt></p>
|
||||||
|
<p> Owner for a range on the unit interval. We are agnostic about its
|
||||||
|
type.</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-owner_weight">owner_weight()</a></h3>
|
||||||
|
<p><tt>owner_weight() = {<a href="#type-owner_name">owner_name()</a>, <a href="#type-weight">weight()</a>}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-owner_weight_list">owner_weight_list()</a></h3>
|
||||||
|
<p><tt>owner_weight_list() = [<a href="#type-owner_weight">owner_weight()</a>]</tt></p>
|
||||||
|
<p> A owner_weight_list is a definition of brick assignments over the
|
||||||
|
unit interval [0.0, 1.0]. The sum of all floats must be 1.0. For
|
||||||
|
example, [{{br1,nd1}, 0.25}, {{br2,nd1}, 0.5}, {{br3,nd1}, 0.25}].</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-weight">weight()</a></h3>
|
||||||
|
<p><tt>weight() = non_neg_integer()</tt></p>
|
||||||
|
<p> For this library, a weight is an integer which specifies the
|
||||||
|
capacity of a "owner" relative to other owners. For example, if
|
||||||
|
owner A with a weight of 10, and if owner B has a weight of 20,
|
||||||
|
then B will be assigned twice as much of the unit interval as A.</p>
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#hash_binary_via_float_map-2">hash_binary_via_float_map/2</a></td><td>Query a float map with a binary (inefficient).</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#hash_binary_via_float_tree-2">hash_binary_via_float_tree/2</a></td><td>Query a float tree with a binary.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_demo_map1-0">make_demo_map1/0</a></td><td>Create a sample float map.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_demo_map2-0">make_demo_map2/0</a></td><td>Create a sample float map.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_float_map-1">make_float_map/1</a></td><td>Create a float map, based on a basic owner weight list.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_float_map-2">make_float_map/2</a></td><td>Create a float map, based on an older float map and a new weight
|
||||||
|
list.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_tree-1">make_tree/1</a></td><td>Create a float tree, which is the rapid lookup data structure
|
||||||
|
for consistent hash queries.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#pretty_with_integers-2">pretty_with_integers/2</a></td><td>Make a pretty/human-friendly version of a float map that describes
|
||||||
|
integer ranges between 1 and <code>Scale</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#pretty_with_integers-3">pretty_with_integers/3</a></td><td>Make a pretty/human-friendly version of a float map (based
|
||||||
|
upon a float map created from <code>OldWeights</code> and <code>NewWeights</code>) that
|
||||||
|
describes integer ranges between 1 and <code>Scale</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#query_tree-2">query_tree/2</a></td><td>Low-level function for querying a float tree: the (floating
|
||||||
|
point) point within the unit interval.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#sum_map_weights-1">sum_map_weights/1</a></td><td>Create a human-friendly summary of a float map.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#zzz_usage_details-0">zzz_usage_details/0</a></td><td>Various usage examples, see source code below this function
|
||||||
|
for full details.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="hash_binary_via_float_map-2">hash_binary_via_float_map/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>hash_binary_via_float_map(Key::binary(), Map::<a href="#type-float_map">float_map()</a>) -> {float(), <a href="#type-owner_name">owner_name()</a>}</tt><br></p>
|
||||||
|
</div><p>Query a float map with a binary (inefficient).</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="hash_binary_via_float_tree-2">hash_binary_via_float_tree/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>hash_binary_via_float_tree(Key::binary(), Tree::<a href="#type-float_tree">float_tree()</a>) -> {float(), <a href="#type-owner_name">owner_name()</a>}</tt><br></p>
|
||||||
|
</div><p>Query a float tree with a binary.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_demo_map1-0">make_demo_map1/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_demo_map1() -> <a href="#type-float_map">float_map()</a></tt><br></p>
|
||||||
|
</div><p>Create a sample float map.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_demo_map2-0">make_demo_map2/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_demo_map2() -> <a href="#type-float_map">float_map()</a></tt><br></p>
|
||||||
|
</div><p>Create a sample float map.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_float_map-1">make_float_map/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_float_map(NewOwnerWeights::<a href="#type-owner_weight_list">owner_weight_list()</a>) -> <a href="#type-float_map">float_map()</a></tt><br></p>
|
||||||
|
</div><p>Create a float map, based on a basic owner weight list.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_float_map-2">make_float_map/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_float_map(OldFloatMap::<a href="#type-float_map">float_map()</a>, NewOwnerWeights::<a href="#type-owner_weight_list">owner_weight_list()</a>) -> <a href="#type-float_map">float_map()</a></tt><br></p>
|
||||||
|
</div><p><p>Create a float map, based on an older float map and a new weight
|
||||||
|
list.</p>
|
||||||
|
|
||||||
|
The weights in the new weight list may be different than (or the
|
||||||
|
same as) whatever weights were used to make the older float map.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_tree-1">make_tree/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_tree(Map::<a href="#type-float_map">float_map()</a>) -> <a href="#type-float_tree">float_tree()</a></tt><br></p>
|
||||||
|
</div><p>Create a float tree, which is the rapid lookup data structure
|
||||||
|
for consistent hash queries.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="pretty_with_integers-2">pretty_with_integers/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>pretty_with_integers(Map::<a href="#type-float_map">float_map()</a>, Scale::integer()) -> [<a href="#type-owner_int_range">owner_int_range()</a>]</tt><br></p>
|
||||||
|
</div><p>Make a pretty/human-friendly version of a float map that describes
|
||||||
|
integer ranges between 1 and <code>Scale</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="pretty_with_integers-3">pretty_with_integers/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>pretty_with_integers(OldWeights::<a href="#type-owner_weight_list">owner_weight_list()</a>, NewWeights::<a href="#type-owner_weight_list">owner_weight_list()</a>, Scale::integer()) -> [<a href="#type-owner_int_range">owner_int_range()</a>]</tt><br></p>
|
||||||
|
</div><p>Make a pretty/human-friendly version of a float map (based
|
||||||
|
upon a float map created from <code>OldWeights</code> and <code>NewWeights</code>) that
|
||||||
|
describes integer ranges between 1 and <code>Scale</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="query_tree-2">query_tree/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>query_tree(Val::float(), Tree::<a href="#type-float_tree">float_tree()</a>) -> {float(), <a href="#type-owner_name">owner_name()</a>}</tt><br></p>
|
||||||
|
</div><p>Low-level function for querying a float tree: the (floating
|
||||||
|
point) point within the unit interval.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="sum_map_weights-1">sum_map_weights/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>sum_map_weights(Map::<a href="#type-float_map">float_map()</a>) -> {{per_owner, <a href="#type-float_map">float_map()</a>}, {weight_sum, float()}}</tt><br></p>
|
||||||
|
</div><p><p>Create a human-friendly summary of a float map.</p>
|
||||||
|
|
||||||
|
The two parts of the summary are: a per-owner total of the unit
|
||||||
|
interval range(s) owned by each owner, and a total sum of all
|
||||||
|
per-owner ranges (which should be 1.0 but is not enforced).</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="zzz_usage_details-0">zzz_usage_details/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>zzz_usage_details() -> any()</tt></p>
|
||||||
|
</div><p>Various usage examples, see source code below this function
|
||||||
|
for full details.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
82
edoc/machi_cinfo.html
Normal file
82
edoc/machi_cinfo.html
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_cinfo</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_cinfo</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>cluster_info callback module for machi specific information
|
||||||
|
gathering.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>cluster_info callback module for machi specific information
|
||||||
|
gathering.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#chain_manager-1">chain_manager/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#cluster_info_generator_funs-0">cluster_info_generator_funs/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#cluster_info_init-0">cluster_info_init/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#dump-0">dump/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#fitness-1">fitness/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#flu1-1">flu1/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#private_projection-1">private_projection/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#public_projection-1">public_projection/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#register-0">register/0</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="chain_manager-1">chain_manager/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>chain_manager(FluName::atom()) -> term()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="cluster_info_generator_funs-0">cluster_info_generator_funs/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>cluster_info_generator_funs() -> [{string(), fun((pid()) -> ok)}]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="cluster_info_init-0">cluster_info_init/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>cluster_info_init() -> ok</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="dump-0">dump/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>dump() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="fitness-1">fitness/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>fitness(FluName::atom()) -> term()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="flu1-1">flu1/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>flu1(FluName::atom()) -> [{atom(), term()}]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="private_projection-1">private_projection/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>private_projection(FluName::atom()) -> [{atom(), term()}]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="public_projection-1">public_projection/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>public_projection(FluName::atom()) -> [{atom(), term()}]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="register-0">register/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>register() -> ok</tt><br></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
44
edoc/machi_config.html
Normal file
44
edoc/machi_config.html
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_config</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_config</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Configuration consulting utilities.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>Configuration consulting utilities. Some conventions:
|
||||||
|
- The function name should match with exact configuration
|
||||||
|
name in <code>app.config</code> or <code>advanced.config</code> of <code>machi</code> section.
|
||||||
|
- The default value of that configuration is expected to be in
|
||||||
|
cuttlefish schema file. Otherwise some macro in headers may
|
||||||
|
be chosen.
|
||||||
|
- Documentation of the configuration is supposed to be written
|
||||||
|
in cuttlefish schema file, rather than @doc section of the function.
|
||||||
|
- spec of the function should be written.
|
||||||
|
- Returning <code>undefined</code> is strongly discouraged. Return some default
|
||||||
|
value instead.
|
||||||
|
- <code>application:get_env/3</code> is recommended. See <code>max_file_size/0</code> for
|
||||||
|
example.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#max_file_size-0">max_file_size/0</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="max_file_size-0">max_file_size/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>max_file_size() -> pos_integer()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
263
edoc/machi_cr_client.html
Normal file
263
edoc/machi_cr_client.html
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_cr_client</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_cr_client</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Erlang API for the Machi client-implemented Chain Replication
|
||||||
|
(CORFU-style) protocol.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Erlang API for the Machi client-implemented Chain Replication
|
||||||
|
(CORFU-style) protocol.</p>
|
||||||
|
|
||||||
|
<p>See also the docs for <a href="machi_flu1_client.html"><code>machi_flu1_client</code></a> for additional
|
||||||
|
details on data types and operation descriptions.</p>
|
||||||
|
|
||||||
|
<p>The API here is much simpler than the <a href="machi_flu1_client.html"><code>machi_flu1_client</code></a> or
|
||||||
|
<a href="machi_proxy_flu1_client.html"><code>machi_proxy_flu1_client</code></a> APIs. This module's API is a
|
||||||
|
proposed simple-but-complete form for clients who are not
|
||||||
|
interested in being an active participant in a Machi cluster and to
|
||||||
|
have the responsibility for Machi internals, i.e., client-side
|
||||||
|
Chain Replication, client-side read repair, client-side tracking of
|
||||||
|
internal Machi epoch & projection changes, etc.</p>
|
||||||
|
|
||||||
|
<p>This client is implemented as a long-lived Erlang process using
|
||||||
|
<code>gen_server</code>-style OTP code practice. A naive client can expect
|
||||||
|
that this process will manage all transient TCP session
|
||||||
|
disconnections and Machi chain reconfigurations. This client's
|
||||||
|
efforts are best-effort and can require some time to retry
|
||||||
|
operations in certain failure cases, i.e., up to several seconds
|
||||||
|
during a Machi projection & epoch change when a new server is
|
||||||
|
added to the chain.</p>
|
||||||
|
|
||||||
|
<p>Doc TODO: Once this API stabilizes, add all relevant data type details
|
||||||
|
to the EDoc here.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4><a name="Missing_API_features">Missing API features</a></h4>
|
||||||
|
|
||||||
|
<p>So far, there is one missing client API feature that ought to be
|
||||||
|
added to Machi in the near future: more flexible checksum
|
||||||
|
management.</p>
|
||||||
|
|
||||||
|
<p>Add a <code>source</code> annotation to all checksums to indicate where the
|
||||||
|
checksum was calculated. For example,</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li> Calculated by client that performed the original chunk append,
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li> Calculated by the 1st Machi server to receive an
|
||||||
|
un-checksummed append request
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li> Re-calculated by Machi to manage fewer checksums of blocks of
|
||||||
|
data larger than the original client-specified chunks.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Client-side checksums would be the "strongest" type of
|
||||||
|
checksum, meaning that any data corruption (of the original
|
||||||
|
data and/or of the checksum itself) can be detected after the
|
||||||
|
client-side calculation. There are too many horror stories on
|
||||||
|
The Net about IP PDUs that are corrupted but unnoticed due to
|
||||||
|
weak TCP checksums, buggy hardware, buggy OS drivers, etc.
|
||||||
|
Checksum versioning is also desirable if/when the current checksum
|
||||||
|
implementation changes from SHA-1 to something else.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4><a name="Implementation_notes">Implementation notes</a></h4>
|
||||||
|
|
||||||
|
<p>The major operation processing is implemented in a state machine-like
|
||||||
|
manner. Before attempting an operation <code>X</code>, there's an initial
|
||||||
|
operation <code>pre-X</code> that takes care of updating the epoch id,
|
||||||
|
restarting client protocol proxies, and if there's any server
|
||||||
|
instability (e.g. some server is wedged), then insert some sleep
|
||||||
|
time. When the chain appears to have stabilized, then we try the <code>X</code>
|
||||||
|
operation again.</p>
|
||||||
|
|
||||||
|
<p>Function name for the <code>pre-X</code> stuff is usually <code>X()</code>, and the
|
||||||
|
function name for the <code>X</code> stuff is usually <code>X2()</code>. (I.e., the <code>X</code>
|
||||||
|
stuff follows after <code>pre-X</code> and therefore has a <code>2</code> suffix on the
|
||||||
|
function name.)</p>
|
||||||
|
|
||||||
|
In the case of read repair, there are two stages: find the value to
|
||||||
|
perform the repair, then perform the repair writes. In the case of
|
||||||
|
the repair writes, the <code>pre-X</code> function is named <code>read_repair3()</code>,
|
||||||
|
and the <code>X</code> function is named <code>read_repair4()</code>.
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append_chunk-3">append_chunk/3</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk-4">append_chunk/4</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-4">append_chunk_extra/4</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-5">append_chunk_extra/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-2">checksum_list/2</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-3">checksum_list/3</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-1">list_files/1</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-2">list_files/2</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#quit-1">quit/1</a></td><td>Quit & close the connection to remote FLU and stop our
|
||||||
|
proxy process.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-5">read_chunk/5</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-6">read_chunk/6</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td>Start a local, long-lived process that will be our steady
|
||||||
|
& reliable communication proxy with the fickle & flaky
|
||||||
|
remote Machi server.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-4">trim_chunk/4</a></td><td>Trim a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-5">trim_chunk/5</a></td><td>Trim a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-4">write_chunk/4</a></td><td>Write a chunk of data (that has already been
|
||||||
|
allocated/sequenced by an earlier append_chunk_extra() call) to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-5">write_chunk/5</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-3">append_chunk/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec, Prefix, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-4">append_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec, Prefix, Chunk, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-4">append_chunk_extra/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(PidSpec, Prefix, Chunk, ChunkExtra) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-5">append_chunk_extra/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(PidSpec, Prefix, Chunk, ChunkExtra, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-2">checksum_list/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec, File) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-3">checksum_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec, File, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-1">list_files/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-2">list_files/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="quit-1">quit/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>quit(PidSpec) -> any()</tt></p>
|
||||||
|
</div><p>Quit & close the connection to remote FLU and stop our
|
||||||
|
proxy process.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-5">read_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec, File, Offset, Size, Opts) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-6">read_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec, File, Offset, Size, Opts, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(P_srvr_list) -> any()</tt></p>
|
||||||
|
</div><p>Start a local, long-lived process that will be our steady
|
||||||
|
& reliable communication proxy with the fickle & flaky
|
||||||
|
remote Machi server.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-2">start_link/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(P_srvr_list, Opts) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-4">trim_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec, File, Offset, Size) -> any()</tt></p>
|
||||||
|
</div><p>Trim a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-5">trim_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec, File, Offset, Size, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Trim a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-4">write_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec, File, Offset, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Write a chunk of data (that has already been
|
||||||
|
allocated/sequenced by an earlier append_chunk_extra() call) to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-5">write_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec, File, Offset, Chunk, Timeout0) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
186
edoc/machi_csum_table.html
Normal file
186
edoc/machi_csum_table.html
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_csum_table</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_csum_table</h1>
|
||||||
|
<ul class="index"><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-byte_sequence">byte_sequence()</a></h3>
|
||||||
|
<p><tt>byte_sequence() = {Offset::non_neg_integer(), Size::pos_integer() | infinity}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-table">table()</a></h3>
|
||||||
|
<p><tt>table() = #machi_csum_table{}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all-1">all/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#all_trimmed-2">all_trimmed/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#all_trimmed-3">all_trimmed/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#any_trimmed-3">any_trimmed/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#calc_unwritten_bytes-1">calc_unwritten_bytes/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#close-1">close/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#decode_csum_file_entry-1">decode_csum_file_entry/1</a></td><td>Decode a single <code>binary()</code> blob into an
|
||||||
|
<code>{Offset,Size,TaggedCSum}</code> tuple.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete-1">delete/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#encode_csum_file_entry-3">encode_csum_file_entry/3</a></td><td>Encode <code>Offset + Size + TaggedCSum</code> into an <code>iolist()</code> type for
|
||||||
|
internal storage by the FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#encode_csum_file_entry_bin-3">encode_csum_file_entry_bin/3</a></td><td>Encode <code>Offset + Size + TaggedCSum</code> into an <code>binary()</code> type for
|
||||||
|
internal storage by the FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#find-3">find/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#find_leftneighbor-2">find_leftneighbor/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#find_rightneighbor-2">find_rightneighbor/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#foldl_chunks-3">foldl_chunks/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#open-2">open/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#split_checksum_list_blob_decode-1">split_checksum_list_blob_decode/1</a></td><td>Split a <code>binary()</code> blob of <code>checksum_list</code> data into a list of
|
||||||
|
<code>{Offset,Size,TaggedCSum}</code> tuples.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#sync-1">sync/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim-3">trim/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim-5">trim/5</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-4">write/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-6">write/6</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="all-1">all/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>all(Machi_csum_table) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="all_trimmed-2">all_trimmed/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>all_trimmed(Machi_csum_table::<a href="#type-table">table()</a>, Pos::non_neg_integer()) -> boolean()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="all_trimmed-3">all_trimmed/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>all_trimmed(Machi_csum_table::<a href="#type-table">table()</a>, Left::non_neg_integer(), Right::non_neg_integer()) -> boolean()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="any_trimmed-3">any_trimmed/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>any_trimmed(CsumT::<a href="#type-table">table()</a>, Offset::pos_integer(), Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>) -> boolean()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="calc_unwritten_bytes-1">calc_unwritten_bytes/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>calc_unwritten_bytes(Machi_csum_table::<a href="#type-table">table()</a>) -> [<a href="#type-byte_sequence">byte_sequence()</a>]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="close-1">close/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>close(Machi_csum_table::<a href="#type-table">table()</a>) -> ok</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="decode_csum_file_entry-1">decode_csum_file_entry/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>decode_csum_file_entry(Else::binary()) -> error | {<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, <a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>}</tt><br></p>
|
||||||
|
</div><p><p>Decode a single <code>binary()</code> blob into an
|
||||||
|
<code>{Offset,Size,TaggedCSum}</code> tuple.</p>
|
||||||
|
|
||||||
|
<p>The internal encoding (which is currently exposed to the outside world
|
||||||
|
via this function and related ones) is:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> 1 byte: record length
|
||||||
|
</li>
|
||||||
|
<li> 8 bytes (unsigned big-endian): byte offset
|
||||||
|
</li>
|
||||||
|
<li> 4 bytes (unsigned big-endian): chunk size
|
||||||
|
</li>
|
||||||
|
<li> all remaining bytes: tagged checksum (1st byte = type tag)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
See <code>machi.hrl</code> for the tagged checksum types, e.g.,
|
||||||
|
<code>?CSUM_TAG_NONE</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete-1">delete/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete(Machi_csum_table::<a href="#type-table">table()</a>) -> ok</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="encode_csum_file_entry-3">encode_csum_file_entry/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>encode_csum_file_entry(Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, TaggedCSum::<a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>) -> iolist()</tt><br></p>
|
||||||
|
</div><p>Encode <code>Offset + Size + TaggedCSum</code> into an <code>iolist()</code> type for
|
||||||
|
internal storage by the FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="encode_csum_file_entry_bin-3">encode_csum_file_entry_bin/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>encode_csum_file_entry_bin(Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, TaggedCSum::<a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>) -> binary()</tt><br></p>
|
||||||
|
</div><p>Encode <code>Offset + Size + TaggedCSum</code> into an <code>binary()</code> type for
|
||||||
|
internal storage by the FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="find-3">find/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>find(Machi_csum_table::<a href="#type-table">table()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-file_size">machi_dt:file_size()</a>) -> [{<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-file_size">machi_dt:file_size()</a>, <a href="machi_dt.html#type-chunk_csum">machi_dt:chunk_csum()</a> | trimmed}]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="find_leftneighbor-2">find_leftneighbor/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>find_leftneighbor(CsumT::<a href="#type-table">table()</a>, Offset::non_neg_integer()) -> undefined | {non_neg_integer(), <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, trimmed | <a href="machi_dt.html#type-chunk_csum">machi_dt:chunk_csum()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="find_rightneighbor-2">find_rightneighbor/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>find_rightneighbor(CsumT::<a href="#type-table">table()</a>, Offset::non_neg_integer()) -> undefined | {non_neg_integer(), <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, trimmed | <a href="machi_dt.html#type-chunk_csum">machi_dt:chunk_csum()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="foldl_chunks-3">foldl_chunks/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>foldl_chunks(Fun::fun(({non_neg_integer(), non_neg_integer(), term()}, Acc0::term()) -> Acc::term()), Acc0::term(), Machi_csum_table::<a href="#type-table">table()</a>) -> Acc::term()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="open-2">open/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>open(CSumFilename::string(), Opts::<a href="proplists.html#type-proplist">proplists:proplist()</a>) -> {ok, <a href="#type-table">table()</a>} | {error, <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="split_checksum_list_blob_decode-1">split_checksum_list_blob_decode/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>split_checksum_list_blob_decode(Bin::binary()) -> {[{<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, <a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>}], TrailingJunk::binary()}</tt><br></p>
|
||||||
|
</div><p>Split a <code>binary()</code> blob of <code>checksum_list</code> data into a list of
|
||||||
|
<code>{Offset,Size,TaggedCSum}</code> tuples.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="sync-1">sync/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>sync(Machi_csum_table::<a href="#type-table">table()</a>) -> ok | {error, <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim-3">trim/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim(Machi_csum_table::<a href="#type-table">table()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-file_size">machi_dt:file_size()</a>) -> ok | {error, <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim-5">trim/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim(CsumT, Offset, Size, LeftUpdate, RightUpdate) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-4">write/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(CsumT::<a href="#type-table">table()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-file_size">machi_dt:file_size()</a>, CSum::<a href="machi_dt.html#type-chunk_csum">machi_dt:chunk_csum()</a> | trimmed) -> ok | {error, trimmed | <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-6">write/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(Machi_csum_table, Offset, Size, CSum, LeftUpdate, RightUpdate) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
110
edoc/machi_dt.html
Normal file
110
edoc/machi_dt.html
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_dt</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_dt</h1>
|
||||||
|
<ul class="index"><li><a href="#types">Data Types</a></li></ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk">chunk()</a></h3>
|
||||||
|
<p><tt>chunk() = <a href="#type-chunk_bin">chunk_bin()</a> | {<a href="#type-chunk_csum">chunk_csum()</a>, <a href="#type-chunk_bin">chunk_bin()</a>}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_bin">chunk_bin()</a></h3>
|
||||||
|
<p><tt>chunk_bin() = binary() | iolist()</tt></p>
|
||||||
|
<p> client can use either</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_csum">chunk_csum()</a></h3>
|
||||||
|
<p><tt>chunk_csum() = binary()</tt></p>
|
||||||
|
<p> 1 byte tag, N-1 bytes checksum</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_pos">chunk_pos()</a></h3>
|
||||||
|
<p><tt>chunk_pos() = {<a href="#type-file_offset">file_offset()</a>, <a href="#type-chunk_size">chunk_size()</a>, <a href="#type-file_name_s">file_name_s()</a>}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_s">chunk_s()</a></h3>
|
||||||
|
<p><tt>chunk_s() = trimmed | binary()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_size">chunk_size()</a></h3>
|
||||||
|
<p><tt>chunk_size() = non_neg_integer()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-chunk_summary">chunk_summary()</a></h3>
|
||||||
|
<p><tt>chunk_summary() = {<a href="#type-file_offset">file_offset()</a>, <a href="#type-chunk_size">chunk_size()</a>, binary()}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-csum_tag">csum_tag()</a></h3>
|
||||||
|
<p><tt>csum_tag() = none | client_sha | server_sha | server_regen_sha</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-epoch_csum">epoch_csum()</a></h3>
|
||||||
|
<p><tt>epoch_csum() = binary()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-epoch_id">epoch_id()</a></h3>
|
||||||
|
<p><tt>epoch_id() = {<a href="#type-epoch_num">epoch_num()</a>, <a href="#type-epoch_csum">epoch_csum()</a>}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-epoch_num">epoch_num()</a></h3>
|
||||||
|
<p><tt>epoch_num() = -1 | non_neg_integer()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-error_general">error_general()</a></h3>
|
||||||
|
<p><tt>error_general() = bad_arg | wedged | bad_checksum</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_info">file_info()</a></h3>
|
||||||
|
<p><tt>file_info() = {<a href="#type-file_size">file_size()</a>, <a href="#type-file_name_s">file_name_s()</a>}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_name">file_name()</a></h3>
|
||||||
|
<p><tt>file_name() = binary() | list()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_name_s">file_name_s()</a></h3>
|
||||||
|
<p><tt>file_name_s() = binary()</tt></p>
|
||||||
|
<p> server reply</p>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_offset">file_offset()</a></h3>
|
||||||
|
<p><tt>file_offset() = non_neg_integer()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_prefix">file_prefix()</a></h3>
|
||||||
|
<p><tt>file_prefix() = binary() | list()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-file_size">file_size()</a></h3>
|
||||||
|
<p><tt>file_size() = non_neg_integer()</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-inet_host">inet_host()</a></h3>
|
||||||
|
<p><tt>inet_host() = <a href="inet.html#type-ip_address">inet:ip_address()</a> | <a href="inet.html#type-hostname">inet:hostname()</a></tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-inet_port">inet_port()</a></h3>
|
||||||
|
<p><tt>inet_port() = <a href="inet.html#type-port_number">inet:port_number()</a></tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-projection">projection()</a></h3>
|
||||||
|
<p><tt>projection() = #projection_v1{}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-projection_type">projection_type()</a></h3>
|
||||||
|
<p><tt>projection_type() = public | private</tt></p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
118
edoc/machi_file_proxy.html
Normal file
118
edoc/machi_file_proxy.html
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_file_proxy</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_file_proxy</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This is a proxy process which mediates access to Machi FLU
|
||||||
|
controlled files.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>This is a proxy process which mediates access to Machi FLU
|
||||||
|
controlled files. In particular, it manages the "write-once register"
|
||||||
|
conceit at the heart of Machi's design.</p>
|
||||||
|
|
||||||
|
<p>Read, write and append requests for a single file will be managed
|
||||||
|
through this proxy. Clients can also request syncs for specific
|
||||||
|
types of filehandles.</p>
|
||||||
|
|
||||||
|
As operations are requested, the proxy keeps track of how many
|
||||||
|
operations it has performed (and how many errors were generated.)
|
||||||
|
After a sufficient number of inactivity, the server terminates
|
||||||
|
itself.
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append-2">append/2</a></td><td>Append data.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append-4">append/4</a></td><td>Append data to file, supplying client metadata and (if desired) a
|
||||||
|
reservation for additional space.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read-3">read/3</a></td><td>Read file at offset for length.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read-4">read/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-3">start_link/3</a></td><td>Start a new instance of the file proxy service.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td>Request to stop an instance of the file proxy service.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#sync-1">sync/1</a></td><td>Force a sync of all filehandles.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#sync-2">sync/2</a></td><td>Force a sync of a specific filehandle type.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim-4">trim/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-3">write/3</a></td><td>Write data at offset.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-4">write/4</a></td><td>Write data at offset, including the client metadata.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append-2">append/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append(Pid::pid(), Data::binary()) -> {ok, File::string(), Offset::non_neg_integer()} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Append data</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append-4">append/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append(Pid::pid(), ClientMeta::<a href="proplists.html#type-proplist">proplists:proplist()</a>, Extra::non_neg_integer(), Data::binary()) -> {ok, File::string(), Offset::non_neg_integer()} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Append data to file, supplying client metadata and (if desired) a
|
||||||
|
reservation for additional space. ClientMeta is a proplist and expects the
|
||||||
|
same keys as write/4.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read-3">read/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read(Pid::pid(), Offset::non_neg_integer(), Length::non_neg_integer()) -> {ok, [{Filename::string(), Offset::non_neg_integer(), Data::binary(), Checksum::binary()}]} | {error, Reason::term()}</tt><br></p>
|
||||||
|
</div><p>Read file at offset for length. This returns a sequence of all
|
||||||
|
written and trimmed (optional) bytes that overlaps with requested
|
||||||
|
offset and length. Borders are not aligned.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read-4">read/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read(Pid::pid(), Offset::non_neg_integer(), Length::non_neg_integer(), Opts::[{no_checksum | no_chunk | needs_trimmed, boolean()}]) -> {ok, [{Filename::string(), Offset::non_neg_integer(), Data::binary(), Checksum::binary()}]} | {error, Reason::term()}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-3">start_link/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName::atom(), Filename::string(), DataDir::string()) -> any()</tt><br></p>
|
||||||
|
</div><p>Start a new instance of the file proxy service. Takes the filename
|
||||||
|
and data directory as arguments. This function is typically called by the
|
||||||
|
<code>machi_file_proxy_sup:start_proxy/2</code> function.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop-1">stop/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop(Pid::pid()) -> ok</tt><br></p>
|
||||||
|
</div><p>Request to stop an instance of the file proxy service.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="sync-1">sync/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>sync(Pid::pid()) -> ok | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Force a sync of all filehandles</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="sync-2">sync/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>sync(Pid::pid(), Type::all | data | csum) -> ok | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Force a sync of a specific filehandle type. Valid types are <code>all</code>, <code>csum</code> and <code>data</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim-4">trim/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim(Pid, Offset, Size, TriggerGC) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-3">write/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(Pid::pid(), Offset::non_neg_integer(), Data::binary()) -> ok | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Write data at offset</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-4">write/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(Pid::pid(), Offset::non_neg_integer(), ClientMeta::<a href="proplists.html#type-proplist">proplists:proplist()</a>, Data::binary()) -> ok | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Write data at offset, including the client metadata. ClientMeta is a proplist
|
||||||
|
that expects the following keys and values:
|
||||||
|
<ul>
|
||||||
|
<li><code>client_csum_tag</code> - the type of checksum from the client as defined in the machi.hrl file</li>
|
||||||
|
<li><code>client_csum</code> - the checksum value from the client</li>
|
||||||
|
</ul></p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
51
edoc/machi_file_proxy_sup.html
Normal file
51
edoc/machi_file_proxy_sup.html
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_file_proxy_sup</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_file_proxy_sup</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This is the main supervisor for the file proxies.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>This is the main supervisor for the file proxies.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#child_spec-1">child_spec/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_proxy-3">start_proxy/3</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="child_spec-1">child_spec/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>child_spec(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_proxy-3">start_proxy/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_proxy(FluName, DataDir, Filename) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
120
edoc/machi_fitness.html
Normal file
120
edoc/machi_fitness.html
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_fitness</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_fitness</h1>
|
||||||
|
<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_admin_down-3">add_admin_down/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete_admin_down-2">delete_admin_down/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#format_status-2">format_status/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_unfit_list-1">get_unfit_list/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#send_fitness_update_spam-3">send_fitness_update_spam/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#send_spam_to_everyone-1">send_spam_to_everyone/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trigger_early_adjustment-2">trigger_early_adjustment/2</a></td><td>For testing purposes, we don't want a test to wait for
|
||||||
|
wall-clock time to elapse before the fitness server makes a
|
||||||
|
down->up status decision.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#update_local_down_list-3">update_local_down_list/3</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="add_admin_down-3">add_admin_down/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>add_admin_down(PidSpec, DownFLU, DownProps) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete_admin_down-2">delete_admin_down/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete_admin_down(PidSpec, DownFLU) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="format_status-2">format_status/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>format_status(Opt, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_unfit_list-1">get_unfit_list/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_unfit_list(PidSpec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(Args) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="send_fitness_update_spam-3">send_fitness_update_spam/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>send_fitness_update_spam(Pid, FromName, Dict) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="send_spam_to_everyone-1">send_spam_to_everyone/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>send_spam_to_everyone(Pid) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(Args) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trigger_early_adjustment-2">trigger_early_adjustment/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trigger_early_adjustment(Pid, FLU) -> any()</tt></p>
|
||||||
|
</div><p>For testing purposes, we don't want a test to wait for
|
||||||
|
wall-clock time to elapse before the fitness server makes a
|
||||||
|
down->up status decision.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="update_local_down_list-3">update_local_down_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>update_local_down_list(PidSpec, Down, MembersDict) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
114
edoc/machi_flu1.html
Normal file
114
edoc/machi_flu1.html
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu1</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu1</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The Machi FLU file server + file location sequencer.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>The Machi FLU file server + file location sequencer.</p>
|
||||||
|
|
||||||
|
<p>This module implements only the Machi FLU file server and its
|
||||||
|
implicit sequencer.
|
||||||
|
Please see the EDoc "Overview" for details about the FLU as a
|
||||||
|
primitive file server process vs. the larger Machi design of a FLU
|
||||||
|
as a sequencer + file server + chain manager group of processes.</p>
|
||||||
|
|
||||||
|
<p>The FLU is named after the CORFU server "FLU" or "FLash Unit" server.</p>
|
||||||
|
|
||||||
|
<h4><a name="Protocol_origins">Protocol origins</a></h4>
|
||||||
|
|
||||||
|
<p>Today's FLU fully supports a protocol that is based on Protocol
|
||||||
|
Buffers. Please see the <code>src/machi.proto</code> file for details.</p>
|
||||||
|
|
||||||
|
<h4><a name="TODO_items">TODO items</a></h4>
|
||||||
|
|
||||||
|
<p>TODO The per-file metadata tuple store is missing from this implementation.</p>
|
||||||
|
|
||||||
|
TODO Section 4.1 ("The FLU") of the Machi design doc suggests that
|
||||||
|
the FLU keep track of the epoch number of the last file write (and
|
||||||
|
perhaps last metadata write), as an optimization for inter-FLU data
|
||||||
|
replication/chain repair.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#current_state-1">current_state/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#format_state-1">format_state/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#main2-4">main2/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_listener_regname-1">make_listener_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_projection_server_regname-1">make_projection_server_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#run_append_server-2">run_append_server/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#run_listen_server-1">run_listen_server/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#update_wedge_state-3">update_wedge_state/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_myself-2">wedge_myself/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="current_state-1">current_state/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>current_state(PidSpec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="format_state-1">format_state/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>format_state(State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="main2-4">main2/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>main2(FluName, TcpPort, DataDir, Props) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_listener_regname-1">make_listener_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_listener_regname(BaseName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_projection_server_regname-1">make_projection_server_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_projection_server_regname(BaseName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="run_append_server-2">run_append_server/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>run_append_server(FluPid, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="run_listen_server-1">run_listen_server/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>run_listen_server(State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(Rest) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop-1">stop/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop(Pid) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="update_wedge_state-3">update_wedge_state/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>update_wedge_state(PidSpec, Boolean, EpochId) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_myself-2">wedge_myself/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_myself(PidSpec, EpochId) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
340
edoc/machi_flu1_client.html
Normal file
340
edoc/machi_flu1_client.html
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu1_client</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu1_client</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Erlang API for the Machi FLU TCP protocol version 1.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Erlang API for the Machi FLU TCP protocol version 1.</p>
|
||||||
|
|
||||||
|
<p>This client API handles low-level PDU serialization/deserialization
|
||||||
|
and low-level TCP session management, e.g. open, receive, write,
|
||||||
|
close. The API for higher-level session management and Machi state
|
||||||
|
management can be found in <a href="machi_proxy_flu1_client.html"><code>machi_proxy_flu1_client</code></a> and
|
||||||
|
<a href="machi_cr_client.html"><code>machi_cr_client</code></a>.</p>
|
||||||
|
|
||||||
|
<p>For the moment, this module implements a Protocol Buffers-based
|
||||||
|
protocol as the sole supported access method to the server,
|
||||||
|
sequencer, and projection store. Conceptually, those three
|
||||||
|
services are independent and ought to have their own protocols. As
|
||||||
|
a practical matter, there is no need for wire protocol
|
||||||
|
compatibility. Furthermore, from the perspective of failure
|
||||||
|
detection, it is very convenient that all three FLU-related
|
||||||
|
services are accessed using the same single TCP port.</p>
|
||||||
|
|
||||||
|
TODO This EDoc was written first, and the EDoc and also <code>-type</code> and
|
||||||
|
<code>-spec</code> definitions for <a href="machi_proxy_flu1_client.html"><code>machi_proxy_flu1_client</code></a> and <a href="machi_cr_client.html"><code>machi_cr_client</code></a> must be improved.
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-port_wrap">port_wrap()</a></h3>
|
||||||
|
<p><tt>port_wrap() = {w, atom(), term()}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append_chunk-4">append_chunk/4</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk-5">append_chunk/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-5">append_chunk_extra/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-6">append_chunk_extra/6</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-3">checksum_list/3</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-4">checksum_list/4</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connect-1">connect/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connected_p-1">connected_p/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete_migration-3">delete_migration/3</a></td><td>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete_migration-4">delete_migration/4</a></td><td>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#disconnect-1">disconnect/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#echo-2">echo/2</a></td><td>Echo -- test protocol round-trip.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#echo-3">echo/3</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-2">get_all_projections/2</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-3">get_all_projections/3</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-2">get_latest_epochid/2</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-3">get_latest_epochid/3</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#kick_projection_reaction-2">kick_projection_reaction/2</a></td><td>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#kick_projection_reaction-3">kick_projection_reaction/3</a></td><td>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-2">list_all_projections/2</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-3">list_all_projections/3</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-2">list_files/2</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-3">list_files/3</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#quit-1">quit/1</a></td><td>Quit & close the connection to remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-6">read_chunk/6</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-7">read_chunk/7</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-2">read_latest_projection/2</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-3">read_latest_projection/3</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-3">read_projection/3</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-4">read_projection/4</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-5">trim_chunk/5</a></td><td>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trunc_hack-3">trunc_hack/3</a></td><td>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trunc_hack-4">trunc_hack/4</a></td><td>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-1">wedge_status/1</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-2">wedge_status/2</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-5">write_chunk/5</a></td><td>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-6">write_chunk/6</a></td><td>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-3">write_projection/3</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-4">write_projection/4</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-4">append_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Prefix::<a href="machi_dt.html#type-file_prefix">machi_dt:file_prefix()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>) -> {ok, <a href="machi_dt.html#type-chunk_pos">machi_dt:chunk_pos()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-5">append_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Prefix::<a href="machi_dt.html#type-file_prefix">machi_dt:file_prefix()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>) -> {ok, <a href="machi_dt.html#type-chunk_pos">machi_dt:chunk_pos()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-5">append_chunk_extra/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Prefix::<a href="machi_dt.html#type-file_prefix">machi_dt:file_prefix()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>, ChunkExtra::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>) -> {ok, <a href="machi_dt.html#type-chunk_pos">machi_dt:chunk_pos()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</p>
|
||||||
|
|
||||||
|
For example, if the <code>Chunk</code> size is 1 KByte and <code>Extra</code> is 4K Bytes, then
|
||||||
|
the file offsets that follow <code>Chunk</code>'s position for the following 4K will
|
||||||
|
be reserved by the file sequencer for later write(s) by the
|
||||||
|
<code>write_chunk()</code> API.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-6">append_chunk_extra/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, Prefix::<a href="machi_dt.html#type-file_prefix">machi_dt:file_prefix()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>, ChunkExtra::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>) -> {ok, <a href="machi_dt.html#type-chunk_pos">machi_dt:chunk_pos()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</p>
|
||||||
|
|
||||||
|
For example, if the <code>Chunk</code> size is 1 KByte and <code>Extra</code> is 4K Bytes, then
|
||||||
|
the file offsets that follow <code>Chunk</code>'s position for the following 4K will
|
||||||
|
be reserved by the file sequencer for later write(s) by the
|
||||||
|
<code>write_chunk()</code> API.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-3">checksum_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> {ok, binary()} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file | partial_read} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-4">checksum_list/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> {ok, binary()} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file} | {error, term()}</tt><br></p>
|
||||||
|
</div><p><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
Why return a simple <code>binary()</code> type rather than
|
||||||
|
<code>[machi_dt:chunk_summary()]</code>? The two reasons are:
|
||||||
|
<ol>
|
||||||
|
<li> Server overhead: the CPU required to chop up the implementation-
|
||||||
|
specific store into zillions of very small terms is very high.
|
||||||
|
</li>
|
||||||
|
<li> Protocol encoding and decoding overhead: the cost is non-zero,
|
||||||
|
and the sum of cost of encoding and decoding a zillion small terms
|
||||||
|
is substantial.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>For both reasons, the server's protocol response is absurdly simple
|
||||||
|
and very fast: send back a <code>binary()</code> blob to the client. Then it
|
||||||
|
is the client's responsibility to spend the CPU time to parse the
|
||||||
|
blob.</p>
|
||||||
|
|
||||||
|
Details of the encoding used inside the <code>binary()</code> blog can be found
|
||||||
|
in the EDoc comments for <a href="machi_flu1.html#decode_csum_file_entry-1"><code>machi_flu1:decode_csum_file_entry/1</code></a>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connect-1">connect/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connect(P_srvr) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connected_p-1">connected_p/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connected_p(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete_migration-3">delete_migration/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete_migration(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete_migration-4">delete_migration/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete_migration(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="disconnect-1">disconnect/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>disconnect(WS) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="echo-2">echo/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>echo(Sock::<a href="#type-port_wrap">port_wrap()</a>, String::string()) -> string() | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Echo -- test protocol round-trip.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="echo-3">echo/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>echo(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, String::string()) -> string() | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-2">get_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, [<a href="machi_dt.html#type-projection">machi_dt:projection()</a>]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-3">get_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, [<a href="machi_dt.html#type-projection">machi_dt:projection()</a>]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-2">get_latest_epochid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, <a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-3">get_latest_epochid/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, <a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="kick_projection_reaction-2">kick_projection_reaction/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>kick_projection_reaction(Sock::<a href="#type-port_wrap">port_wrap()</a>, Options::list()) -> ok</tt><br></p>
|
||||||
|
</div><p>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="kick_projection_reaction-3">kick_projection_reaction/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>kick_projection_reaction(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, Options::list()) -> ok</tt><br></p>
|
||||||
|
</div><p>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-2">list_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, [non_neg_integer()]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-3">list_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, [non_neg_integer()]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-2">list_files/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>) -> {ok, [<a href="machi_dt.html#type-file_info">machi_dt:file_info()</a>]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-3">list_files/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>) -> {ok, [<a href="machi_dt.html#type-file_info">machi_dt:file_info()</a>]} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="quit-1">quit/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>quit(Sock::<a href="#type-port_wrap">port_wrap()</a>) -> ok</tt><br></p>
|
||||||
|
</div><p>Quit & close the connection to remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-6">read_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, Opts::<a href="proplists.html#type-proplist">proplists:proplist()</a>) -> {ok, <a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | not_written | partial_read} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-7">read_chunk/7</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, Opts::<a href="proplists.html#type-proplist">proplists:proplist()</a>) -> {ok, <a href="machi_dt.html#type-chunk_s">machi_dt:chunk_s()</a>} | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | not_written | partial_read} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-2">read_latest_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, <a href="machi_dt.html#type-projection">machi_dt:projection()</a>} | {error, not_written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-3">read_latest_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>) -> {ok, <a href="machi_dt.html#type-projection">machi_dt:projection()</a>} | {error, not_written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-3">read_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>, Epoch::<a href="machi_dt.html#type-epoch_num">machi_dt:epoch_num()</a>) -> {ok, <a href="machi_dt.html#type-projection">machi_dt:projection()</a>} | {error, not_written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-4">read_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>, Epoch::<a href="machi_dt.html#type-epoch_num">machi_dt:epoch_num()</a>) -> {ok, <a href="machi_dt.html#type-projection">machi_dt:projection()</a>} | {error, not_written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-5">trim_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File0::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trunc_hack-3">trunc_hack/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trunc_hack(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trunc_hack-4">trunc_hack/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trunc_hack(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a> | no_such_file} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-1">wedge_status/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(Sock::<a href="#type-port_wrap">port_wrap()</a>) -> {ok, {boolean(), <a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>}} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-2">wedge_status/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>) -> {ok, {boolean(), <a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>}} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-5">write_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(Sock::<a href="#type-port_wrap">port_wrap()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-6">write_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, EpochID::<a href="machi_dt.html#type-epoch_id">machi_dt:epoch_id()</a>, File::<a href="machi_dt.html#type-file_name">machi_dt:file_name()</a>, Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Chunk::<a href="machi_dt.html#type-chunk">machi_dt:chunk()</a>) -> ok | {error, <a href="machi_dt.html#type-error_general">machi_dt:error_general()</a>} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-3">write_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(Sock::<a href="#type-port_wrap">port_wrap()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>, Proj::<a href="machi_dt.html#type-projection">machi_dt:projection()</a>) -> ok | {error, written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-4">write_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(Host::<a href="machi_dt.html#type-inet_host">machi_dt:inet_host()</a>, TcpPort::<a href="machi_dt.html#type-inet_port">machi_dt:inet_port()</a>, ProjType::<a href="machi_dt.html#type-projection_type">machi_dt:projection_type()</a>, Proj::<a href="machi_dt.html#type-projection">machi_dt:projection()</a>) -> ok | {error, written} | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
119
edoc/machi_flu_filename_mgr.html
Normal file
119
edoc/machi_flu_filename_mgr.html
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu_filename_mgr</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu_filename_mgr</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This process is responsible for managing filenames assigned to
|
||||||
|
prefixes.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>This process is responsible for managing filenames assigned to
|
||||||
|
prefixes. It's started out of <code>machi_flu_psup</code>.</p>
|
||||||
|
|
||||||
|
<p>Supported operations include finding the "current" filename assigned to
|
||||||
|
a prefix. Incrementing the sequence number and returning a new file name
|
||||||
|
and listing all data files assigned to a given prefix.</p>
|
||||||
|
|
||||||
|
<p>All prefixes should have the form of <code>{prefix, P}</code>. Single filename
|
||||||
|
return values have the form of <code>{file, F}</code>.</p>
|
||||||
|
|
||||||
|
<h2>Finding the current file associated with a sequence</h2><p>
|
||||||
|
First it looks up the sequence number from the prefix name. If
|
||||||
|
no sequence file is found, it uses 0 as the sequence number and searches
|
||||||
|
for a matching file with the prefix and 0 as the sequence number.
|
||||||
|
If no file is found, the it generates a new filename by incorporating
|
||||||
|
the given prefix, a randomly generated (v4) UUID and 0 as the
|
||||||
|
sequence number.</p>
|
||||||
|
|
||||||
|
If the sequence number is > 0, then the process scans the filesystem
|
||||||
|
looking for a filename which matches the prefix and given sequence number and
|
||||||
|
returns that.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#child_spec-2">child_spec/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#find_or_make_filename_from_prefix-3">find_or_make_filename_from_prefix/3</a></td><td>Find the latest available or make a filename from a prefix.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#increment_prefix_sequence-2">increment_prefix_sequence/2</a></td><td>Increment the sequence counter for a given prefix.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files_by_prefix-2">list_files_by_prefix/2</a></td><td>Given a prefix in the form of <code>{prefix, P}</code> return
|
||||||
|
all the data files associated with that prefix.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="child_spec-2">child_spec/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>child_spec(FluName, DataDir) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, State, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="find_or_make_filename_from_prefix-3">find_or_make_filename_from_prefix/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>find_or_make_filename_from_prefix(FluName::atom(), EpochId::<a href="#type-pv1_epoch_n">pv1_epoch_n()</a>, Prefix::{prefix, string()}) -> {file, Filename::string()} | {error, Reason::term()} | timeout</tt><br></p>
|
||||||
|
</div><p>Find the latest available or make a filename from a prefix. A prefix
|
||||||
|
should be in the form of a tagged tuple <code>{prefix, P}</code>. Returns a tagged
|
||||||
|
tuple in the form of <code>{file, F}</code> or an <code>{error, Reason}</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Req, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Req, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="increment_prefix_sequence-2">increment_prefix_sequence/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>increment_prefix_sequence(FluName::atom(), Prefix::{prefix, string()}) -> ok | {error, Reason::term()} | timeout</tt><br></p>
|
||||||
|
</div><p>Increment the sequence counter for a given prefix. Prefix should
|
||||||
|
be in the form of <code>{prefix, P}</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files_by_prefix-2">list_files_by_prefix/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files_by_prefix(FluName::atom(), Prefix::{prefix, string()}) -> [<a href="file.html#type-name">file:name()</a>] | timeout | {error, Reason::term()}</tt><br></p>
|
||||||
|
</div><p>Given a prefix in the form of <code>{prefix, P}</code> return
|
||||||
|
all the data files associated with that prefix. Returns
|
||||||
|
a list.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-2">start_link/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName, DataDir) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
123
edoc/machi_flu_metadata_mgr.html
Normal file
123
edoc/machi_flu_metadata_mgr.html
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu_metadata_mgr</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu_metadata_mgr</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This is a metadata service for the machi FLU which currently
|
||||||
|
tracks the mappings between filenames and file proxies.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>This is a metadata service for the machi FLU which currently
|
||||||
|
tracks the mappings between filenames and file proxies.</p>
|
||||||
|
|
||||||
|
<p>The service takes a given hash space and spreads it out over a
|
||||||
|
pool of N processes which are responsible for 1/Nth the hash
|
||||||
|
space. When a user requests an operation on a particular file
|
||||||
|
the filename is hashed into the hash space and the request
|
||||||
|
forwarded to a particular manager responsible for that slice
|
||||||
|
of the hash space.</p>
|
||||||
|
|
||||||
|
The current hash implementation is <code>erlang:phash2/1</code> which has
|
||||||
|
a range between 0..2^27-1 or 134,217,727.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#build_metadata_mgr_name-2">build_metadata_mgr_name/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#child_spec-4">child_spec/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#lookup_manager_pid-2">lookup_manager_pid/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#lookup_proxy_pid-2">lookup_proxy_pid/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-4">start_link/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_proxy_pid-2">start_proxy_pid/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop_proxy_pid-2">stop_proxy_pid/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_file-2">trim_file/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="build_metadata_mgr_name-2">build_metadata_mgr_name/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>build_metadata_mgr_name(FluName, N) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="child_spec-4">child_spec/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>child_spec(FluName, C, DataDir, N) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, State, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Req, From, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Req, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="lookup_manager_pid-2">lookup_manager_pid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>lookup_manager_pid(FluName, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="lookup_proxy_pid-2">lookup_proxy_pid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>lookup_proxy_pid(FluName, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-4">start_link/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName, Name, DataDir, Num) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_proxy_pid-2">start_proxy_pid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_proxy_pid(FluName, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop_proxy_pid-2">stop_proxy_pid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop_proxy_pid(FluName, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_file-2">trim_file/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_file(FluName, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
49
edoc/machi_flu_metadata_mgr_sup.html
Normal file
49
edoc/machi_flu_metadata_mgr_sup.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu_metadata_mgr_sup</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu_metadata_mgr_sup</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This is the supervisor for the collection of metadata
|
||||||
|
managers.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>This is the supervisor for the collection of metadata
|
||||||
|
managers. It's started out of <code>machi_flu_psup</code>. It reads an
|
||||||
|
application environment variable named <code>metadata_manager_count</code>
|
||||||
|
with a default of 10 if it is not set.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#child_spec-3">child_spec/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-3">start_link/3</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="child_spec-3">child_spec/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>child_spec(FluName, DataDir, N) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-3">start_link/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName, DataDir, N) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
136
edoc/machi_flu_psup.html
Normal file
136
edoc/machi_flu_psup.html
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu_psup</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu_psup</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Supervisor for Machi FLU servers and their related support
|
||||||
|
servers.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Supervisor for Machi FLU servers and their related support
|
||||||
|
servers.</p>
|
||||||
|
|
||||||
|
<p>Our parent supervisor, <a href="machi_flu_sup.html"><code>machi_flu_sup</code></a>, is responsible for
|
||||||
|
managing FLUs as a single entity. However, the actual
|
||||||
|
implementation of a FLU includes three major Erlang processes (not
|
||||||
|
including support/worker procs): the FLU itself, the FLU's
|
||||||
|
projection store, and the FLU's local chain manager. This
|
||||||
|
supervisor is responsible for managing those three major services
|
||||||
|
as a single "package", to be started & stopped together.</p>
|
||||||
|
|
||||||
|
<p>The illustration below shows the OTP process supervision tree for
|
||||||
|
the Machi application. Two FLUs are running, called <code>a</code> and <code>b</code>.
|
||||||
|
The chain is configured for a third FLU, <code>c</code>, which is not running
|
||||||
|
at this time.</p>
|
||||||
|
|
||||||
|
<p><img src="/machi//images/supervisor-2flus.png"></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> The FLU process itself is named <code>a</code>.
|
||||||
|
</li>
|
||||||
|
<li> The projection store process is named <code>a_pstore</code>.
|
||||||
|
</li>
|
||||||
|
<li> The chain manager process is named <code>a_chmgr</code>. The three
|
||||||
|
linked subprocesses are long-lived <a href="machi_proxy_flu1_client.html"><code>machi_proxy_flu1_client</code></a> processes for communicating to all
|
||||||
|
chain participants' projection stores (including the local
|
||||||
|
store <code>a_pstore</code>).
|
||||||
|
</li>
|
||||||
|
<li> A fourth major process, <code>a_listener</code>, which is responsible for
|
||||||
|
listening on a TCP socket and creating new connections.
|
||||||
|
Currently, each listener has two processes handling incoming
|
||||||
|
requests, one from each chain manager proxy.
|
||||||
|
</li>
|
||||||
|
<li> Note that the sub-supervisor parent of <code>a</code> and <code>a_listener</code> does
|
||||||
|
not have a registered name.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_fitness_regname-1">make_fitness_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_flu_regname-1">make_flu_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_mgr_supname-1">make_mgr_supname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_p_regname-1">make_p_regname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_package_spec-1">make_package_spec/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_package_spec-4">make_package_spec/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_proj_supname-1">make_proj_supname/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_flu_package-1">start_flu_package/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_flu_package-4">start_flu_package/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-4">start_link/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop_flu_package-1">stop_flu_package/1</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_fitness_regname-1">make_fitness_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_fitness_regname(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_flu_regname-1">make_flu_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_flu_regname(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_mgr_supname-1">make_mgr_supname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_mgr_supname(MgrName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_p_regname-1">make_p_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_p_regname(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_package_spec-1">make_package_spec/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_package_spec(P_srvr) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_package_spec-4">make_package_spec/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_package_spec(FluName, TcpPort, DataDir, Props) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_proj_supname-1">make_proj_supname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_proj_supname(ProjName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_flu_package-1">start_flu_package/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_flu_package(P_srvr) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_flu_package-4">start_flu_package/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_flu_package(FluName, TcpPort, DataDir, Props) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-4">start_link/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(FluName, TcpPort, DataDir, Props) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop_flu_package-1">stop_flu_package/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop_flu_package(FluName) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
53
edoc/machi_flu_sup.html
Normal file
53
edoc/machi_flu_sup.html
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_flu_sup</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_flu_sup</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Supervisor for Machi FLU servers and their related support
|
||||||
|
servers.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Supervisor for Machi FLU servers and their related support
|
||||||
|
servers.</p>
|
||||||
|
|
||||||
|
<p>Responsibility for managing FLU and chain lifecycle after the initial
|
||||||
|
application startup is delegated to <a href="machi_lifecycle_mgr.html"><code>machi_lifecycle_mgr</code></a>.</p>
|
||||||
|
|
||||||
|
See <a href="machi_flu_psup.html"><code>machi_flu_psup</code></a> for an illustration of the entire Machi
|
||||||
|
application process structure.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#load_rc_d_files_from_dir-1">load_rc_d_files_from_dir/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="load_rc_d_files_from_dir-1">load_rc_d_files_from_dir/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>load_rc_d_files_from_dir(Dir) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-0">start_link/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
229
edoc/machi_lifecycle_mgr.html
Normal file
229
edoc/machi_lifecycle_mgr.html
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_lifecycle_mgr</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_lifecycle_mgr</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Lifecycle manager for Machi FLUs and chains.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Lifecycle manager for Machi FLUs and chains.</p>
|
||||||
|
|
||||||
|
<p>Over the lifetime of a Machi cluster, both the number and types of
|
||||||
|
FLUs and chains may change. The lifecycle manager is responsible
|
||||||
|
for implementing the lifecycle changes as expressed by "policy".
|
||||||
|
In our case, "policy" is created by an external administrative
|
||||||
|
entity that creates and deletes configuration files that define
|
||||||
|
FLUs and chains relative to this local machine.</p>
|
||||||
|
|
||||||
|
<p>The "master configuration" for deciding which FLUs should be
|
||||||
|
running on this machine was inspired by BSD UNIX's <code>init(8)</code> and the
|
||||||
|
"rc.d" scheme. FLU definitions are found in a single directory,
|
||||||
|
with one file per FLU. Chains are defined similarly, with one
|
||||||
|
definition file per chain.</p>
|
||||||
|
|
||||||
|
<p>If a definition file for a FLU (or chain) exists, then that
|
||||||
|
FLU/chain ought to be configured into being and running. If a
|
||||||
|
definition file for a FLU/chain is removed, then that FLU/chain
|
||||||
|
should be stopped gracefully. However, deleting of a file destroys
|
||||||
|
information that is stored inside of that file. Therefore, we will
|
||||||
|
<b>not allow arbitrary unlinking of lifecycle config files</b>. If
|
||||||
|
the administrator deletes these config files using <code>unlink(8)</code>
|
||||||
|
directly, then "the warranty has been broken".</p>
|
||||||
|
|
||||||
|
<p>We will rely on using an administrative command to inform the
|
||||||
|
running system to stop and/or delete lifecycle resources. If the
|
||||||
|
Machi application is not running, sorry, please start Machi first.</p>
|
||||||
|
|
||||||
|
<h3><a name="Wheel_reinvention">Wheel reinvention</a></h3>
|
||||||
|
|
||||||
|
<p>There's a whole mess of configuration management research &
|
||||||
|
libraries out there. I hope to ignore them all by doing something
|
||||||
|
quick & dirty & good enough here. If I fail, then I'll go
|
||||||
|
pay attention to That Other Stuff.</p>
|
||||||
|
|
||||||
|
<h3><a name="A_note_about_policy">A note about policy</a></h3>
|
||||||
|
|
||||||
|
<p>It is outside of the scope of this local lifecycle manager to make
|
||||||
|
decisions about policy or to distribute policy info/files/whatever
|
||||||
|
to other machines. This is our machine. There are many like it,
|
||||||
|
but this one is ours.</p>
|
||||||
|
|
||||||
|
<h3><a name="Machi_Application_Variables">Machi Application Variables</a></h3>
|
||||||
|
|
||||||
|
<p>All OTP application environment variables below are defined in the
|
||||||
|
<code>machi</code> application.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> <tt>flu_config_dir</tt>: Stores the <code>rc.d-</code>like config files for
|
||||||
|
FLU runtime policy.
|
||||||
|
</li>
|
||||||
|
<li> <tt>flu_data_dir</tt>: Stores the file data and metadata for
|
||||||
|
all FLUs.
|
||||||
|
</li>
|
||||||
|
<li> <tt>chain_config_dir</tt>: Stores the <code>rc.d</code>-like config files for
|
||||||
|
chain runtime policy.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3><a name="The_FLU_Lifecycle">The FLU Lifecycle</a></h3>
|
||||||
|
|
||||||
|
<p>FLUs on the local machine may be started and stopped, as defined by
|
||||||
|
administrative policy. In order to do any useful work, however, a
|
||||||
|
running FLU must also be configured to be a member of a replication
|
||||||
|
chain. Thus, as a practical matter, both a FLU and the chain that
|
||||||
|
the FLU participates in must both be managed by this manager.</p>
|
||||||
|
|
||||||
|
<p>When a new <code>rc.d</code>-style config file is written to the FLU
|
||||||
|
definition directory, a Machi server process will discover the file
|
||||||
|
within a certain period of time, e.g. 15 seconds. The FLU will be
|
||||||
|
started with the file's specified parameters. A FLU should be
|
||||||
|
defined and started before configuring its chain membership.</p>
|
||||||
|
|
||||||
|
<p>Usually a FLU is removed implicitly by removing that FLU from the a
|
||||||
|
newer definition file for the chain, or by deleting the entire
|
||||||
|
chain definition. If a FLU has been started but never been a chain
|
||||||
|
member, then the FLU can be stopped & removed explicitly.</p>
|
||||||
|
|
||||||
|
<p>When a FLU has been removed by policy, the FLU's data files are set
|
||||||
|
aside into a temporary area. An additional policy command may be
|
||||||
|
used to permanently delete such FLUs' data files, i.e. to reclaim
|
||||||
|
disk space.</p>
|
||||||
|
|
||||||
|
<p>Resources for the FLU are defined in <code>machi_projection.hrl</code>
|
||||||
|
in the <code>p_srvr{}</code> record. The major elements of this record are:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li> <tt>name :: atom()</tt>: The name of the FLU. This name
|
||||||
|
should be unique over the lifetime of the administrative
|
||||||
|
domain and thus managed by outside policy. This name must be
|
||||||
|
the same as the name of the <code>rc.d</code>-style config file that
|
||||||
|
defines the FLU.
|
||||||
|
</li>
|
||||||
|
<li> <tt>address :: string()</tt>: The DNS hostname or IP address
|
||||||
|
used by other servers to communicate with this FLU.
|
||||||
|
</li>
|
||||||
|
<li> <tt>port :: non_neg_integer() </tt>: The TCP port number that
|
||||||
|
the FLU listens to for incoming Protocol Buffers-serialized
|
||||||
|
communication.
|
||||||
|
</li>
|
||||||
|
<li> <tt>props :: property_list()</tt>: A general-purpose property
|
||||||
|
list. Its use is currently fluid & not well-defined yet.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3><a name="The_Chain_Lifecycle">The Chain Lifecycle</a></h3>
|
||||||
|
|
||||||
|
<p>If a FLU on the local machine is expected to participate in a
|
||||||
|
replication chain, then an <code>rc.d</code>-style chain definition file must
|
||||||
|
also be present on each machine that runs a FLU in the chain.</p>
|
||||||
|
|
||||||
|
<p>Machi's chains are self-managing, via Humming Consensus; see the
|
||||||
|
<a href="https://github.com/basho/machi/tree/master/doc/" target="_top"><tt>https://github.com/basho/machi/tree/master/doc/</tt></a> directory for
|
||||||
|
much more detail about Humming Consensus. After FLUs have received
|
||||||
|
their initial chain configuration for Humming Consensus, the FLUs
|
||||||
|
will manage each other (and the chain) themselves.</p>
|
||||||
|
|
||||||
|
<p>However, Humming Consensus does not handle three chain management
|
||||||
|
problems: 1. specifying the very first chain configuration,
|
||||||
|
2. altering the membership of the chain (adding/removing FLUs from
|
||||||
|
the chain), or 3. stopping the chain permanently.</p>
|
||||||
|
|
||||||
|
<p>FLUs in a new chain should have definition files created on each
|
||||||
|
FLU's respective machine prior to defining their chain. Similarly,
|
||||||
|
on each machine that hosts a chain member, a chain definition file
|
||||||
|
created. External policy is responsible for creating each of these
|
||||||
|
files.</p>
|
||||||
|
|
||||||
|
<p>Resources for the chain are defined in <code>machi_projection.hrl</code>
|
||||||
|
in the <code>chain_def_v1{}</code> record. The major elements of this record are:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li> <tt>name :: atom()</tt>: The name of the chain. This name
|
||||||
|
should be unique over the lifetime of the administrative
|
||||||
|
domain and thus managed by outside policy. This name must be
|
||||||
|
the same as the name of the <code>rc.d</code>-style config file that
|
||||||
|
defines the chain.
|
||||||
|
</li>
|
||||||
|
<li> <tt>mode :: 'ap_mode' | 'cp_mode'</tt>: This is the consistency
|
||||||
|
to be used for managing the chain's replicated data: eventual
|
||||||
|
consistency and strong consistency, respectively.
|
||||||
|
</li>
|
||||||
|
<li> <tt>full :: [#p_srvr{}] </tt>: A list of <code>#p_srvr{}</code> records
|
||||||
|
to define the full-service members of the chain.
|
||||||
|
</li>
|
||||||
|
<li> <tt>witnesses :: [#p_srvr{}] </tt>: A list of <code>#p_srvr{}</code> records
|
||||||
|
to define the witness-only members of the chain. Witness servers
|
||||||
|
may only be used with strong consistency mode.
|
||||||
|
</li>
|
||||||
|
<li> <tt>props :: property_list()</tt>: A general-purpose property
|
||||||
|
list. Its use is currently fluid & not well-defined yet.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3><a name="Conflicts_with_TCP_ports,_FLU_&_chain_names,_etc">Conflicts with TCP ports, FLU & chain names, etc</a></h3>
|
||||||
|
|
||||||
|
This manager is not responsible for managing conflicts in resource
|
||||||
|
namespaces, e.g., TCP port numbers, FLU names, chain names, etc.
|
||||||
|
Managing these namespaces is external policy's responsibility.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, State, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-0">start_link/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, State) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
69
edoc/machi_merkle_tree.html
Normal file
69
edoc/machi_merkle_tree.html
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_merkle_tree</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_merkle_tree</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Creates a Merkle tree per file based on the checksum data for
|
||||||
|
a given data file.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Creates a Merkle tree per file based on the checksum data for
|
||||||
|
a given data file.</p>
|
||||||
|
|
||||||
|
<p>The <code>naive</code> implementation representation is:</p>
|
||||||
|
|
||||||
|
<p><code><<Length:64, Offset:32, 0>></code> for unwritten bytes
|
||||||
|
<code><<Length:64, Offset:32, 1>></code> for trimmed bytes
|
||||||
|
<code><<Length:64, Offset:32, Csum/binary>></code> for written bytes</p>
|
||||||
|
|
||||||
|
The tree feeds these leaf nodes into hashes representing chunks of a minimum
|
||||||
|
size of at least 1024 KB (1 MB), but if the file size is larger, we will try
|
||||||
|
to get about 100 chunks for the first rollup "Level 1." We aim for around 10
|
||||||
|
hashes at level 2, and then 2 hashes level 3 and finally the root.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#diff-2">diff/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#filename-1">filename/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#open-2">open/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#open-3">open/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#tree-1">tree/1</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="diff-2">diff/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>diff(Mt, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="filename-1">filename/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>filename(Mt) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="open-2">open/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>open(Filename, DataDir) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="open-3">open/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>open(Filename, DataDir, Type) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="tree-1">tree/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>tree(Mt) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
204
edoc/machi_pb_high_client.html
Normal file
204
edoc/machi_pb_high_client.html
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_pb_high_client</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_pb_high_client</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Machi PB (Protocol Buffers) high-level client (prototype, API TBD).
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Machi PB (Protocol Buffers) high-level client (prototype, API TBD)</p>
|
||||||
|
|
||||||
|
At the moment, this is brittle-prototype-quality code: the API is not yet
|
||||||
|
fully specified, there is very little error handling with respect
|
||||||
|
to a single socket connection, and there is no code to deal with
|
||||||
|
multiple connections/load balancing/error handling to several/all
|
||||||
|
Machi cluster servers.
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-machi_client_error_reason">machi_client_error_reason()</a></h3>
|
||||||
|
<p><tt>machi_client_error_reason() = bad_arg | wedged | bad_checksum | partition | not_written | written | trimmed | no_such_file | partial_read | bad_epoch | <a href="inet.html#type-posix">inet:posix()</a></tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append_chunk-6">append_chunk/6</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk-7">append_chunk/7</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#auth-3">auth/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#auth-4">auth/4</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-2">checksum_list/2</a></td><td>Returns a binary that has checksums and chunks encoded inside
|
||||||
|
(This is because encoding-decoding them are inefficient).</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-3">checksum_list/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connected_p-1">connected_p/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#convert_general_status_code-1">convert_general_status_code/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#echo-2">echo/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#echo-3">echo/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-1">list_files/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-2">list_files/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#quit-1">quit/1</a></td><td>Stops a client process.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-5">read_chunk/5</a></td><td>Tries to read a chunk of a specified file.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-6">read_chunk/6</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td>Creates a client process.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-4">trim_chunk/4</a></td><td>Trims arbitrary binary range of any file.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-5">trim_chunk/5</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-5">write_chunk/5</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-6">write_chunk/6</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-6">append_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec::pid(), PlacementKey::binary(), Prefix::binary(), Chunk::binary(), CSum::binary(), ChunkExtra::non_neg_integer()) -> {ok, Filename::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-7">append_chunk/7</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec::pid(), PlacementKey::binary(), Prefix::binary(), Chunk::binary(), CSum::binary(), ChunkExtra::non_neg_integer(), Timeout::non_neg_integer()) -> {ok, Filename::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="auth-3">auth/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>auth(PidSpec::pid(), User::string(), Pass::string()) -> ok | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="auth-4">auth/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>auth(PidSpec::pid(), User::string(), Pass::string(), Timeout::non_neg_integer()) -> ok | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-2">checksum_list/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec::pid(), File::string()) -> {ok, binary()} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div><p>Returns a binary that has checksums and chunks encoded inside
|
||||||
|
(This is because encoding-decoding them are inefficient). TODO:
|
||||||
|
return a structured list of them.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-3">checksum_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec, File, Timeout) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connected_p-1">connected_p/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connected_p(PidSpec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="convert_general_status_code-1">convert_general_status_code/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>convert_general_status_code(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="echo-2">echo/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>echo(PidSpec::pid(), String::string()) -> {ok, string()} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="echo-3">echo/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>echo(PidSpec::pid(), String::string(), Timeout::non_neg_integer()) -> {ok, string()} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-1">list_files/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-2">list_files/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec, Timeout) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="quit-1">quit/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>quit(PidSpec::pid()) -> ok</tt><br></p>
|
||||||
|
</div><p>Stops a client process.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-5">read_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec::pid(), File::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, Options::[{flag_no_checksum | flag_no_chunk | needs_trimmed, boolean()}]) -> {ok, {Chunks::[{File::string(), <a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, binary()}], Trimmed::[{File::string(), <a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>}]}} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div><p>Tries to read a chunk of a specified file. It returns <code>{ok,
|
||||||
|
{Chunks, TrimmedChunks}}</code> for live file while it returns <code>{error,
|
||||||
|
trimmed}</code> if all bytes of the file was trimmed.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-6">read_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec::pid(), File::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, Options::[{flag_no_checksum | flag_no_chunk | needs_trimmed, boolean()}], Timeout::non_neg_integer()) -> {ok, {Chunks::[{File::string(), <a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>, binary()}], Trimmed::[{File::string(), <a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, <a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>}]}} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(P_srvr_list::<a href="#type-p_srvr_dict">p_srvr_dict()</a>) -> {ok, pid()} | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div><p>Creates a client process</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-4">trim_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec::pid(), File::string(), Offset::non_neg_integer(), Size::<a href="machi_dt.html#type-chunk_size">machi_dt:chunk_size()</a>) -> ok | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div><p>Trims arbitrary binary range of any file. If a specified range
|
||||||
|
has any byte trimmed, it fails and returns <code>{error, trimmed}</code>.
|
||||||
|
Otherwise it trims all bytes in that range. If there are
|
||||||
|
overlapping chunks with client-specified checksum, they will cut
|
||||||
|
off and checksum are re-calculated in server side. TODO: Add
|
||||||
|
option specifying whether to trigger GC.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-5">trim_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec, File, Offset, Size, Timeout) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-5">write_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec::pid(), File::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Chunk::binary(), CSum::binary()) -> ok | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-6">write_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec::pid(), File::string(), Offset::<a href="machi_dt.html#type-file_offset">machi_dt:file_offset()</a>, Chunk::binary(), CSum::binary(), Timeout::non_neg_integer()) -> ok | {error, <a href="#type-machi_client_error_reason">machi_client_error_reason()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
edoc/machi_pb_server.html
Normal file
31
edoc/machi_pb_server.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_pb_server</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_pb_server</h1>
|
||||||
|
<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#run_loop-2">run_loop/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="run_loop-2">run_loop/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>run_loop(Sock, P_srvr_list) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Jun 25 2015, 16:39:10.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
55
edoc/machi_pb_translate.html
Normal file
55
edoc/machi_pb_translate.html
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_pb_translate</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_pb_translate</h1>
|
||||||
|
<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#conv_to_csum_tag-1">conv_to_csum_tag/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#from_pb_request-1">from_pb_request/1</a></td><td>Adapt impedence mismatches between Erlang and Protocol Buffers.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#from_pb_response-1">from_pb_response/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#to_pb_request-2">to_pb_request/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#to_pb_response-3">to_pb_response/3</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="conv_to_csum_tag-1">conv_to_csum_tag/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>conv_to_csum_tag(Type) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="from_pb_request-1">from_pb_request/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>from_pb_request(Mpb_ll_request) -> any()</tt></p>
|
||||||
|
</div><p>Adapt impedence mismatches between Erlang and Protocol Buffers.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="from_pb_response-1">from_pb_response/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>from_pb_response(Mpb_ll_response) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="to_pb_request-2">to_pb_request/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>to_pb_request(ReqID, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="to_pb_response-3">to_pb_response/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>to_pb_response(ReqID, X2, X) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
77
edoc/machi_pb_wrap.html
Normal file
77
edoc/machi_pb_wrap.html
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_pb_wrap</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_pb_wrap</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Wrappers for Protocol Buffers encoding, including hacks to fix
|
||||||
|
impedance mismatches between Erlang terms and PB encodings.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>Wrappers for Protocol Buffers encoding, including hacks to fix
|
||||||
|
impedance mismatches between Erlang terms and PB encodings.
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#dec_p_srvr-1">dec_p_srvr/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#dec_projection_v1-1">dec_projection_v1/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#enc_p_srvr-1">enc_p_srvr/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#enc_projection_v1-1">enc_projection_v1/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_projection_req-2">make_projection_req/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_projection_resp-3">make_projection_resp/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#unmake_projection_req-1">unmake_projection_req/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#unmake_projection_resp-1">unmake_projection_resp/1</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="dec_p_srvr-1">dec_p_srvr/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>dec_p_srvr(Bin) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="dec_projection_v1-1">dec_projection_v1/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>dec_projection_v1(Bin) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="enc_p_srvr-1">enc_p_srvr/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>enc_p_srvr(P) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="enc_projection_v1-1">enc_projection_v1/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>enc_projection_v1(P) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_projection_req-2">make_projection_req/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_projection_req(ID, X2) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_projection_resp-3">make_projection_resp/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_projection_resp(ID, X2, Status) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="unmake_projection_req-1">unmake_projection_req/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>unmake_projection_req(Mpb_ll_request) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="unmake_projection_resp-1">unmake_projection_resp/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>unmake_projection_resp(Mpb_ll_response) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Jun 25 2015, 16:39:10.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
61
edoc/machi_plist.html
Normal file
61
edoc/machi_plist.html
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_plist</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_plist</h1>
|
||||||
|
<ul class="index"><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="types">Data Types</a></h2>
|
||||||
|
|
||||||
|
<h3 class="typedecl"><a name="type-plist">plist()</a></h3>
|
||||||
|
<p><tt>plist() = #machi_plist{}</tt></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add-2">add/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#all-1">all/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#close-1">close/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#find-2">find/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#open-2">open/2</a></td><td>persistent list of binaries.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="add-2">add/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>add(Plist::<a href="#type-plist">plist()</a>, Name::string()) -> {ok, <a href="#type-plist">plist()</a>} | {error, <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="all-1">all/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>all(Machi_plist::<a href="#type-plist">plist()</a>) -> [<a href="file.html#type-filename">file:filename()</a>]</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="close-1">close/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>close(Machi_plist::<a href="#type-plist">plist()</a>) -> ok</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="find-2">find/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>find(Machi_plist::<a href="#type-plist">plist()</a>, Name::string()) -> boolean()</tt><br></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="open-2">open/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>open(Filename::<a href="file.html#type-filename_all">file:filename_all()</a>, Opt::<a href="proplists.html#type-proplist">proplists:proplist()</a>) -> {ok, <a href="#type-plist">plist()</a>} | {error, <a href="file.html#type-posix">file:posix()</a>}</tt><br></p>
|
||||||
|
</div><p>persistent list of binaries</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
106
edoc/machi_projection.html
Normal file
106
edoc/machi_projection.html
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_projection</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_projection</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>API for manipulating Machi projection data structures (i.e., records).
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>API for manipulating Machi projection data structures (i.e., records).
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#compare-2">compare/2</a></td><td>Compare two projection records for equality (assuming that the
|
||||||
|
checksum element has been correctly calculated).</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_epoch_id-1">get_epoch_id/1</a></td><td>Return the epoch_id of the projection.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_epoch_id-1">make_epoch_id/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_members_dict-1">make_members_dict/1</a></td><td>Make a <code>p_srvr_dict()</code> out of a list of <code>p_srvr()</code> or out of a
|
||||||
|
<code>p_srvr_dict()</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_summary-1">make_summary/1</a></td><td>Create a proplist-style summary of a projection record.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#new-6">new/6</a></td><td>Create a new projection record.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#new-7">new/7</a></td><td>Create a new projection record.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#new-8">new/8</a></td><td>Create a new projection record.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#update_checksum-1">update_checksum/1</a></td><td>Update the checksum element of a projection record.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#update_dbg2-2">update_dbg2/2</a></td><td>Update the <code>dbg2</code> element of a projection record.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="compare-2">compare/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>compare(Projection_v1::#projection_v1{}, Projection_v1::#projection_v1{}) -> integer()</tt><br></p>
|
||||||
|
</div><p><p>Compare two projection records for equality (assuming that the
|
||||||
|
checksum element has been correctly calculated).</p>
|
||||||
|
|
||||||
|
The name "compare" is probably too close to "rank"? This
|
||||||
|
comparison has nothing to do with projection ranking.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_epoch_id-1">get_epoch_id/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_epoch_id(Projection_v1) -> any()</tt></p>
|
||||||
|
</div><p>Return the epoch_id of the projection.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_epoch_id-1">make_epoch_id/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_epoch_id(Projection_v1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_members_dict-1">make_members_dict/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_members_dict(Ps::[<a href="#type-p_srvr">p_srvr()</a>] | <a href="#type-p_srvr_dict">p_srvr_dict()</a>) -> <a href="#type-p_srvr_dict">p_srvr_dict()</a></tt><br></p>
|
||||||
|
</div><p><p>Make a <code>p_srvr_dict()</code> out of a list of <code>p_srvr()</code> or out of a
|
||||||
|
<code>p_srvr_dict()</code>.</p>
|
||||||
|
|
||||||
|
<p>If <code>Ps</code> is a <code>p_srvr_dict()</code>, then this function is usually a
|
||||||
|
no-op. However, if someone has tampered with the list and screwed
|
||||||
|
up its order, then we should fix it so <code>orddict</code> can work
|
||||||
|
correctly.</p>
|
||||||
|
|
||||||
|
If <code>Ps</code> is simply <code>list(p_srvr())</code>, in which case we'll convert it
|
||||||
|
to a <code>p_srvr_dict()</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_summary-1">make_summary/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_summary(Projection_v1) -> any()</tt></p>
|
||||||
|
</div><p>Create a proplist-style summary of a projection record.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="new-6">new/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>new(MyName, MemberDict, Down_list, UPI_list, Repairing_list, Ps) -> any()</tt></p>
|
||||||
|
</div><p>Create a new projection record.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="new-7">new/7</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>new(EpochNum, MyName, MemberDict, Down_list, UPI_list, Repairing_list, Dbg) -> any()</tt></p>
|
||||||
|
</div><p>Create a new projection record.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="new-8">new/8</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>new(EpochNum, MyName, MembersDict0, Down_list, UPI_list, Repairing_list, Dbg, Dbg2) -> any()</tt></p>
|
||||||
|
</div><p><p>Create a new projection record.</p>
|
||||||
|
|
||||||
|
The <code>MemberDict0</code> argument may be a true <code>p_srvr_dict()</code> (i.e, it
|
||||||
|
is a well-formed <code>orddict</code> with the correct 2-tuple key-value form)
|
||||||
|
or it may be simply <code>list(p_srvr())</code>, in which case we'll convert it
|
||||||
|
to a <code>p_srvr_dict()</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="update_checksum-1">update_checksum/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>update_checksum(P) -> any()</tt></p>
|
||||||
|
</div><p>Update the checksum element of a projection record.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="update_dbg2-2">update_dbg2/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>update_dbg2(P, Dbg2) -> any()</tt></p>
|
||||||
|
</div><p>Update the <code>dbg2</code> element of a projection record.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
181
edoc/machi_projection_store.html
Normal file
181
edoc/machi_projection_store.html
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_projection_store</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_projection_store</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The Machi write-once projection store service.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>The Machi write-once projection store service.</p>
|
||||||
|
|
||||||
|
<p>This API is gen_server-style message passing, intended for use
|
||||||
|
within a single Erlang node to glue together the projection store
|
||||||
|
server with the node-local process that implements Machi's FLU
|
||||||
|
client access protocol (on the "server side" of the TCP connection).</p>
|
||||||
|
|
||||||
|
<p>All Machi client access to the projection store SHOULD NOT use this
|
||||||
|
module's API. Instead, clients should access indirectly via <a href="machi_cr_client.html"><code>machi_cr_client</code></a>, <a href="machi_proxy_flu1_client.html"><code>machi_proxy_flu1_client</code></a>, or <a href="machi_flu1_client.html"><code>machi_flu1_client</code></a>.</p>
|
||||||
|
|
||||||
|
The projection store is implemented by an Erlang/OTP <code>gen_server</code>
|
||||||
|
process that is associated with each FLU. Conceptually, the
|
||||||
|
projection store is an array of write-once registers. For each
|
||||||
|
projection store register, the key is a 2-tuple of an epoch number
|
||||||
|
(<code>non_neg_integer()</code> type) and a projection type (<code>public</code> or
|
||||||
|
<code>private</code> type); the value is a projection data structure
|
||||||
|
(<code>projection_v1()</code> type).
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-2">get_all_projections/2</a></td><td>Fetch all projection records of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-3">get_all_projections/3</a></td><td>Fetch all projection records of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-2">get_latest_epochid/2</a></td><td>Fetch the latest epoch number + checksum for type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-3">get_latest_epochid/3</a></td><td>Fetch the latest epoch number + checksum for type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_wedge_notify_pid-1">get_wedge_notify_pid/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-2">list_all_projections/2</a></td><td>Fetch all projection epoch numbers of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-3">list_all_projections/3</a></td><td>Fetch all projection epoch numbers of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read-3">read/3</a></td><td>Fetch the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read-4">read/4</a></td><td>Fetch the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-2">read_latest_projection/2</a></td><td>Fetch the latest projection record for type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-3">read_latest_projection/3</a></td><td>Fetch the latest projection record for type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#set_consistency_mode-2">set_consistency_mode/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#set_wedge_notify_pid-2">set_wedge_notify_pid/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-3">start_link/3</a></td><td>Start a new projection store server.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-3">write/3</a></td><td>Write the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write-4">write/4</a></td><td>Write the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-2">get_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Fetch all projection records of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-3">get_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch all projection records of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-2">get_latest_epochid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the latest epoch number + checksum for type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-3">get_latest_epochid/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the latest epoch number + checksum for type <code>ProjType</code>.
|
||||||
|
projection.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_wedge_notify_pid-1">get_wedge_notify_pid/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_wedge_notify_pid(PidSpec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-2">list_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Fetch all projection epoch numbers of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-3">list_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch all projection epoch numbers of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read-3">read/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read(PidSpec, ProjType, Epoch) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read-4">read/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read(PidSpec, ProjType, Epoch, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-2">read_latest_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the latest projection record for type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-3">read_latest_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the latest projection record for type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="set_consistency_mode-2">set_consistency_mode/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>set_consistency_mode(PidSpec, CMode) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="set_wedge_notify_pid-2">set_wedge_notify_pid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>set_wedge_notify_pid(PidSpec, NotifyWedgeStateChanges) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-3">start_link/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(RegName, DataDir, NotifyWedgeStateChanges) -> any()</tt></p>
|
||||||
|
</div><p><p>Start a new projection store server.</p>
|
||||||
|
|
||||||
|
The <code>DataDir</code> argument should be the same directory as specified
|
||||||
|
for use by our companion FLU data server -- all file system paths
|
||||||
|
used by this server are intended to be stored underneath a common
|
||||||
|
file system parent directory as the FLU data server & sequencer
|
||||||
|
servers.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-3">write/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(PidSpec, ProjType, Proj) -> any()</tt></p>
|
||||||
|
</div><p>Write the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write-4">write/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write(PidSpec, ProjType, Proj, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Write the projection record type <code>ProjType</code> for epoch number <code>Epoch</code> .</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
323
edoc/machi_proxy_flu1_client.html
Normal file
323
edoc/machi_proxy_flu1_client.html
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_proxy_flu1_client</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_proxy_flu1_client</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Erlang API for the Machi FLU TCP protocol version 1, with a
|
||||||
|
proxy-process style API for hiding messy details such as TCP
|
||||||
|
connection/disconnection with the remote Machi server.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Erlang API for the Machi FLU TCP protocol version 1, with a
|
||||||
|
proxy-process style API for hiding messy details such as TCP
|
||||||
|
connection/disconnection with the remote Machi server.</p>
|
||||||
|
|
||||||
|
<p>Machi is intentionally avoiding using distributed Erlang for
|
||||||
|
Machi's communication. This design decision makes Erlang-side code
|
||||||
|
more difficult & complex, but it's the price to pay for some
|
||||||
|
language independence. Later in Machi's life cycle, we may (?) need to
|
||||||
|
(re-)implement some components in a non-Erlang/BEAM-based language.</p>
|
||||||
|
|
||||||
|
<p>This module implements a "man in the middle" proxy between the
|
||||||
|
Erlang client and Machi server (which is on the "far side" of a TCP
|
||||||
|
connection to somewhere). This proxy process will always execute
|
||||||
|
on the same Erlang node as the Erlang client that uses it. The
|
||||||
|
proxy is intended to be a stable, long-lived process that survives
|
||||||
|
TCP communication problems with the remote server.</p>
|
||||||
|
|
||||||
|
For a higher level interface, see <a href="machi_cr_client.html"><code>machi_cr_client</code></a>.
|
||||||
|
For a lower level interface, see <a href="machi_flu1_client.html"><code>machi_flu1_client</code></a>.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append_chunk-4">append_chunk/4</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk-5">append_chunk/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-5">append_chunk_extra/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-6">append_chunk_extra/6</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-3">checksum_list/3</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-4">checksum_list/4</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-2">get_all_projections/2</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-3">get_all_projections/3</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_epoch_id-1">get_epoch_id/1</a></td><td>Get the <code>epoch_id()</code> of the FLU's current/latest projection.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_epoch_id-2">get_epoch_id/2</a></td><td>Get the <code>epoch_id()</code> of the FLU's current/latest projection.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-2">get_latest_epochid/2</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epochid-3">get_latest_epochid/3</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#kick_projection_reaction-2">kick_projection_reaction/2</a></td><td>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#kick_projection_reaction-3">kick_projection_reaction/3</a></td><td>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-2">list_all_projections/2</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-3">list_all_projections/3</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-2">list_files/2</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-3">list_files/3</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#quit-1">quit/1</a></td><td>Quit & close the connection to remote FLU and stop our
|
||||||
|
proxy process.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-6">read_chunk/6</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-7">read_chunk/7</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-2">read_latest_projection/2</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-3">read_latest_projection/3</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-3">read_projection/3</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-4">read_projection/4</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td>Start a local, long-lived process that will be our steady
|
||||||
|
& reliable communication proxy with the fickle & flaky
|
||||||
|
remote Machi server.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_proxies-1">start_proxies/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#stop_proxies-1">stop_proxies/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-5">trim_chunk/5</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trim_chunk-6">trim_chunk/6</a></td><td>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-1">wedge_status/1</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-2">wedge_status/2</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-5">write_chunk/5</a></td><td>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-6">write_chunk/6</a></td><td>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-3">write_projection/3</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-4">write_projection/4</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-4">append_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec, EpochID, Prefix, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-5">append_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(PidSpec, EpochID, Prefix, Chunk, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-5">append_chunk_extra/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(PidSpec, EpochID, Prefix, Chunk, ChunkExtra) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-6">append_chunk_extra/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(PidSpec, EpochID, Prefix, Chunk, ChunkExtra, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-3">checksum_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-4">checksum_list/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(PidSpec, EpochID, File, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>code_change(OldVsn, S, Extra) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-2">get_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-3">get_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_epoch_id-1">get_epoch_id/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_epoch_id(PidSpec) -> any()</tt></p>
|
||||||
|
</div><p>Get the <code>epoch_id()</code> of the FLU's current/latest projection.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_epoch_id-2">get_epoch_id/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_epoch_id(PidSpec, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Get the <code>epoch_id()</code> of the FLU's current/latest projection.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-2">get_latest_epochid/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epochid-3">get_latest_epochid/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epochid(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_call(Request, From, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_cast(Msg, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>handle_info(Info, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="kick_projection_reaction-2">kick_projection_reaction/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>kick_projection_reaction(PidSpec, Options) -> any()</tt></p>
|
||||||
|
</div><p>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="kick_projection_reaction-3">kick_projection_reaction/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>kick_projection_reaction(PidSpec, Options, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Kick (politely) the remote chain manager to react to a
|
||||||
|
projection change.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-2">list_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-3">list_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-2">list_files/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec, EpochID) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-3">list_files/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(PidSpec, EpochID, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="quit-1">quit/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>quit(PidSpec) -> any()</tt></p>
|
||||||
|
</div><p>Quit & close the connection to remote FLU and stop our
|
||||||
|
proxy process.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-6">read_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec, EpochID, File, Offset, Size, Opts) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-7">read_chunk/7</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(PidSpec, EpochID, File, Offset, Size, Opts, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-2">read_latest_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(PidSpec, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-3">read_latest_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(PidSpec, ProjType, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-3">read_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(PidSpec, ProjType, Epoch) -> any()</tt></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-4">read_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(PidSpec, ProjType, Epoch, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link(P_srvr) -> any()</tt></p>
|
||||||
|
</div><p>Start a local, long-lived process that will be our steady
|
||||||
|
& reliable communication proxy with the fickle & flaky
|
||||||
|
remote Machi server.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_proxies-1">start_proxies/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_proxies(MembersDict) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="stop_proxies-1">stop_proxies/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>stop_proxies(ProxiesDict) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>terminate(Reason, S) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-5">trim_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec, EpochID, File, Offset, Size) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trim_chunk-6">trim_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trim_chunk(PidSpec, EpochID, File, Offset, Chunk, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-1">wedge_status/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(PidSpec) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-2">wedge_status/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(PidSpec, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-5">write_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec, EpochID, File, Offset, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-6">write_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(PidSpec, EpochID, File, Offset, Chunk, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Write a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-3">write_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(PidSpec, ProjType, Proj) -> any()</tt></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-4">write_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(PidSpec, ProjType, Proj, Timeout) -> any()</tt></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
edoc/machi_sequencer.html
Normal file
23
edoc/machi_sequencer.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_sequencer</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_sequencer</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li></ul>"Mothballed" sequencer code, perhaps to be reused sometime in
|
||||||
|
the future?.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>"Mothballed" sequencer code, perhaps to be reused sometime in
|
||||||
|
the future?<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Jul 1 2015, 18:32:19.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
42
edoc/machi_sup.html
Normal file
42
edoc/machi_sup.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_sup</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_sup</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Top Machi application supervisor.
|
||||||
|
|
||||||
|
<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2><p>Top Machi application supervisor.</p>
|
||||||
|
|
||||||
|
See <a href="machi_flu_psup.html"><code>machi_flu_psup</code></a> for an illustration of the entire Machi
|
||||||
|
application process structure.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="init-1">init/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>init(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="start_link-0">start_link/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>start_link() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
288
edoc/machi_util.html
Normal file
288
edoc/machi_util.html
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_util</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_util</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Miscellaneous utility functions.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>Miscellaneous utility functions.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#bin_to_hexstr-1">bin_to_hexstr/1</a></td><td>Convert a <code>binary()</code> to a hexadecimal string.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#bool2int-1">bool2int/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_chunk-1">checksum_chunk/1</a></td><td>Calculate a checksum for a chunk of file data.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#combinations-1">combinations/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connect-2">connect/2</a></td><td>Create a TCP connection to a remote Machi server.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connect-3">connect/3</a></td><td>Create a TCP connection to a remote Machi server.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#hexstr_to_bin-1">hexstr_to_bin/1</a></td><td>Convert a hexadecimal string to a <code>binary()</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#hexstr_to_int-1">hexstr_to_int/1</a></td><td>Convert a hexadecimal string to an integer.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#increment_max_filenum-2">increment_max_filenum/2</a></td><td>Increase the file size of a config file, which is used as the
|
||||||
|
basis for a minimum sequence number.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#info_msg-2">info_msg/2</a></td><td>Log an 'info' level message.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#int2bool-1">int2bool/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#int_to_hexbin-2">int_to_hexbin/2</a></td><td>Convert an integer into a hexadecimal string (in <code>binary()</code>
|
||||||
|
form) whose length is based on <code>I_size</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#int_to_hexstr-2">int_to_hexstr/2</a></td><td>Convert an integer into a hexadecimal string whose length is
|
||||||
|
based on <code>I_size</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#is_valid_filename-1">is_valid_filename/1</a></td><td>Given a filename, return true if it is a valid machi filename,
|
||||||
|
false otherwise.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_binary-1">make_binary/1</a></td><td>Convert a compatible Erlang data type into a <code>binary()</code> equivalent.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_checksum_filename-2">make_checksum_filename/2</a></td><td>Calculate a checksum file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_checksum_filename-4">make_checksum_filename/4</a></td><td>Calculate a checksum file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_config_filename-2">make_config_filename/2</a></td><td>Calculate a config file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_data_filename-2">make_data_filename/2</a></td><td>Calculate a file data file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_data_filename-4">make_data_filename/4</a></td><td>Calculate a file data file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_projection_filename-2">make_projection_filename/2</a></td><td>Calculate a projection store file path, by common convention.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_regname-1">make_regname/1</a></td><td>Create a registered name atom for FLU sequencer internal
|
||||||
|
rendezvous/message passing use.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_string-1">make_string/1</a></td><td>Convert a compatible Erlang data type into a <code>string()</code> equivalent.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_tagged_csum-1">make_tagged_csum/1</a></td><td>Create a tagged checksum.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#make_tagged_csum-2">make_tagged_csum/2</a></td><td>Makes tagged csum.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#mbytes-1">mbytes/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#mk_order-2">mk_order/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#ordered_combinations-1">ordered_combinations/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#parse_filename-1">parse_filename/1</a></td><td>Given a machi filename, return a set of components in a list.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#perms-1">perms/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#permutations-1">permutations/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#pretty_time-0">pretty_time/0</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#pretty_time-2">pretty_time/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_max_filenum-2">read_max_filenum/2</a></td><td>Read the file size of a config file, which is used as the
|
||||||
|
basis for a minimum sequence number.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#unmake_tagged_csum-1">unmake_tagged_csum/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#verb-1">verb/1</a></td><td>Log a verbose message.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#verb-2">verb/2</a></td><td>Log a verbose message.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wait_for_death-2">wait_for_death/2</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wait_for_life-2">wait_for_life/2</a></td><td></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="bin_to_hexstr-1">bin_to_hexstr/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>bin_to_hexstr(X1::binary()) -> string()</tt><br></p>
|
||||||
|
</div><p>Convert a <code>binary()</code> to a hexadecimal string.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="bool2int-1">bool2int/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>bool2int(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_chunk-1">checksum_chunk/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_chunk(Chunk::binary() | iolist()) -> binary()</tt><br></p>
|
||||||
|
</div><p>Calculate a checksum for a chunk of file data.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="combinations-1">combinations/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>combinations(L) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connect-2">connect/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connect(Host::<a href="inet.html#type-ip_address">inet:ip_address()</a> | <a href="inet.html#type-hostname">inet:hostname()</a>, Port::<a href="inet.html#type-port_number">inet:port_number()</a>) -> port()</tt><br></p>
|
||||||
|
</div><p>Create a TCP connection to a remote Machi server.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connect-3">connect/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connect(Host::<a href="inet.html#type-ip_address">inet:ip_address()</a> | <a href="inet.html#type-hostname">inet:hostname()</a>, Port::<a href="inet.html#type-port_number">inet:port_number()</a>, Timeout::timeout()) -> port()</tt><br></p>
|
||||||
|
</div><p>Create a TCP connection to a remote Machi server.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="hexstr_to_bin-1">hexstr_to_bin/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>hexstr_to_bin(S::string() | binary()) -> binary()</tt><br></p>
|
||||||
|
</div><p>Convert a hexadecimal string to a <code>binary()</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="hexstr_to_int-1">hexstr_to_int/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>hexstr_to_int(X::string() | binary()) -> non_neg_integer()</tt><br></p>
|
||||||
|
</div><p>Convert a hexadecimal string to an integer.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="increment_max_filenum-2">increment_max_filenum/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>increment_max_filenum(DataDir::string(), Prefix::string()) -> ok | {error, term()}</tt><br></p>
|
||||||
|
</div><p>Increase the file size of a config file, which is used as the
|
||||||
|
basis for a minimum sequence number.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="info_msg-2">info_msg/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>info_msg(Fmt::string(), Args::list()) -> term()</tt><br></p>
|
||||||
|
</div><p>Log an 'info' level message.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="int2bool-1">int2bool/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>int2bool(I) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="int_to_hexbin-2">int_to_hexbin/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>int_to_hexbin(I::non_neg_integer(), I_size::non_neg_integer()) -> binary()</tt><br></p>
|
||||||
|
</div><p>Convert an integer into a hexadecimal string (in <code>binary()</code>
|
||||||
|
form) whose length is based on <code>I_size</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="int_to_hexstr-2">int_to_hexstr/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>int_to_hexstr(I::non_neg_integer(), I_size::non_neg_integer()) -> string()</tt><br></p>
|
||||||
|
</div><p>Convert an integer into a hexadecimal string whose length is
|
||||||
|
based on <code>I_size</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="is_valid_filename-1">is_valid_filename/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>is_valid_filename(Filename::string()) -> true | false</tt><br></p>
|
||||||
|
</div><p>Given a filename, return true if it is a valid machi filename,
|
||||||
|
false otherwise.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_binary-1">make_binary/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_binary(X::binary() | iolist()) -> binary()</tt><br></p>
|
||||||
|
</div><p>Convert a compatible Erlang data type into a <code>binary()</code> equivalent.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_checksum_filename-2">make_checksum_filename/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_checksum_filename(DataDir::string(), FileName::[] | string() | binary()) -> string()</tt><br></p>
|
||||||
|
</div><p>Calculate a checksum file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_checksum_filename-4">make_checksum_filename/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_checksum_filename(DataDir::string(), Prefix::string(), SequencerName::atom() | string() | binary(), FileNum::integer()) -> string()</tt><br></p>
|
||||||
|
</div><p>Calculate a checksum file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_config_filename-2">make_config_filename/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_config_filename(DataDir::string(), Prefix::string()) -> string()</tt><br></p>
|
||||||
|
</div><p>Calculate a config file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_data_filename-2">make_data_filename/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_data_filename(DataDir::string(), File::[] | string() | binary()) -> {binary(), string()}</tt><br></p>
|
||||||
|
</div><p>Calculate a file data file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_data_filename-4">make_data_filename/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_data_filename(DataDir::string(), Prefix::string(), SequencerName::atom() | string() | binary(), FileNum::integer() | string()) -> {binary(), string()}</tt><br></p>
|
||||||
|
</div><p>Calculate a file data file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_projection_filename-2">make_projection_filename/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_projection_filename(DataDir::string(), File::[] | string()) -> string()</tt><br></p>
|
||||||
|
</div><p>Calculate a projection store file path, by common convention.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_regname-1">make_regname/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_regname(Prefix::binary() | string()) -> atom()</tt><br></p>
|
||||||
|
</div><p>Create a registered name atom for FLU sequencer internal
|
||||||
|
rendezvous/message passing use.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_string-1">make_string/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_string(X::binary() | iolist()) -> string()</tt><br></p>
|
||||||
|
</div><p>Convert a compatible Erlang data type into a <code>string()</code> equivalent.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_tagged_csum-1">make_tagged_csum/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_tagged_csum(X1) -> any()</tt></p>
|
||||||
|
</div><p>Create a tagged checksum</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="make_tagged_csum-2">make_tagged_csum/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>make_tagged_csum(X1::<a href="machi_dt.html#type-csum_tag">machi_dt:csum_tag()</a>, SHA::binary()) -> <a href="machi_dt.html#type-chunk_csum">machi_dt:chunk_csum()</a></tt><br></p>
|
||||||
|
</div><p>Makes tagged csum. Each meanings are:
|
||||||
|
none / ?CSUM_TAG_NONE
|
||||||
|
- a suspicious and nonsense checksum
|
||||||
|
client_sha / ?CSUM_TAG_CLIENT_SHA
|
||||||
|
- a valid checksum given by client and stored in server
|
||||||
|
server_sha / ?CSUM_TAG_SERVER_SHA
|
||||||
|
- a valid checksum generated by and stored in server
|
||||||
|
server_regen_sha / ?CSUM_TAG_SERVER_REGEN_SHA
|
||||||
|
- a valid checksum generated by server in an ad hoc manner, not stored in server</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="mbytes-1">mbytes/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>mbytes(Size) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="mk_order-2">mk_order/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>mk_order(UPI2, Repair1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="ordered_combinations-1">ordered_combinations/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>ordered_combinations(Master) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="parse_filename-1">parse_filename/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>parse_filename(Filename::string()) -> [string()]</tt><br></p>
|
||||||
|
</div><p>Given a machi filename, return a set of components in a list.
|
||||||
|
The components will be:
|
||||||
|
<ul>
|
||||||
|
<li>Prefix</li>
|
||||||
|
<li>UUID</li>
|
||||||
|
<li>Sequence number</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
Invalid filenames will return an empty list.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="perms-1">perms/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>perms(L) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="permutations-1">permutations/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>permutations(L) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="pretty_time-0">pretty_time/0</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>pretty_time() -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="pretty_time-2">pretty_time/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>pretty_time(X1, MSec) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_max_filenum-2">read_max_filenum/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_max_filenum(DataDir::string(), Prefix::string()) -> non_neg_integer()</tt><br></p>
|
||||||
|
</div><p>Read the file size of a config file, which is used as the
|
||||||
|
basis for a minimum sequence number.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="unmake_tagged_csum-1">unmake_tagged_csum/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>unmake_tagged_csum(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verb-1">verb/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verb(Fmt::string()) -> ok</tt><br></p>
|
||||||
|
</div><p>Log a verbose message.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="verb-2">verb/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>verb(Fmt::string(), Args::list()) -> ok</tt><br></p>
|
||||||
|
</div><p>Log a verbose message.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wait_for_death-2">wait_for_death/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wait_for_death(Pid, Iters) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wait_for_life-2">wait_for_life/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wait_for_life(Reg, Iters) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
260
edoc/machi_yessir_client.html
Normal file
260
edoc/machi_yessir_client.html
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Module machi_yessir_client</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Module machi_yessir_client</h1>
|
||||||
|
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>"Yes, sir!" style dummy/mock client facade.
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="description">Description</a></h2>"Yes, sir!" style dummy/mock client facade.
|
||||||
|
<h2><a name="index">Function Index</a></h2>
|
||||||
|
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#append_chunk-4">append_chunk/4</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk-5">append_chunk/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-5">append_chunk_extra/5</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#append_chunk_extra-6">append_chunk_extra/6</a></td><td>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-3">checksum_list/3</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#checksum_list-4">checksum_list/4</a></td><td>Fetch the list of chunk checksums for <code>File</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connect-1">connect/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#connected_p-1">connected_p/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete_migration-3">delete_migration/3</a></td><td>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#delete_migration-4">delete_migration/4</a></td><td>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#disconnect-1">disconnect/1</a></td><td></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-2">get_all_projections/2</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_all_projections-3">get_all_projections/3</a></td><td>Get all projections from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epoch-2">get_latest_epoch/2</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#get_latest_epoch-3">get_latest_epoch/3</a></td><td>Get the latest epoch number + checksum from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-2">list_all_projections/2</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_all_projections-3">list_all_projections/3</a></td><td>Get all epoch numbers from the FLU's projection store.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-2">list_files/2</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#list_files-3">list_files/3</a></td><td>Fetch the list of all files on the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#quit-1">quit/1</a></td><td>Quit & close the connection to remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-5">read_chunk/5</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_chunk-6">read_chunk/6</a></td><td>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-2">read_latest_projection/2</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_latest_projection-3">read_latest_projection/3</a></td><td>Get the latest projection from the FLU's projection store for <code>ProjType</code></td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-3">read_projection/3</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#read_projection-4">read_projection/4</a></td><td>Read a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trunc_hack-3">trunc_hack/3</a></td><td>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#trunc_hack-4">trunc_hack/4</a></td><td>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-1">wedge_status/1</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#wedge_status-2">wedge_status/2</a></td><td>Fetch the wedge status from the remote FLU.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-5">write_chunk/5</a></td><td>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_chunk-6">write_chunk/6</a></td><td>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-3">write_projection/3</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
<tr><td valign="top"><a href="#write_projection-4">write_projection/4</a></td><td>Write a projection <code>Proj</code> of type <code>ProjType</code>.</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2><a name="functions">Function Details</a></h2>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-4">append_chunk/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(Sock, EpochID, Prefix, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk-5">append_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk(Host, TcpPort, EpochID, Prefix, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-5">append_chunk_extra/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(Yessir, EpochID, Prefix, Chunk, ChunkExtra) -> any()</tt></p>
|
||||||
|
</div><p><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</p>
|
||||||
|
|
||||||
|
For example, if the <code>Chunk</code> size is 1 KByte and <code>Extra</code> is 4K Bytes, then
|
||||||
|
the file offsets that follow <code>Chunk</code>'s position for the following 4K will
|
||||||
|
be reserved by the file sequencer for later write(s) by the
|
||||||
|
<code>write_chunk()</code> API.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="append_chunk_extra-6">append_chunk_extra/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>append_chunk_extra(Host, TcpPort, EpochID, Prefix, Chunk, ChunkExtra) -> any()</tt></p>
|
||||||
|
</div><p><p>Append a chunk (binary- or iolist-style) of data to a file
|
||||||
|
with <code>Prefix</code> and also request an additional <code>Extra</code> bytes.</p>
|
||||||
|
|
||||||
|
For example, if the <code>Chunk</code> size is 1 KByte and <code>Extra</code> is 4K Bytes, then
|
||||||
|
the file offsets that follow <code>Chunk</code>'s position for the following 4K will
|
||||||
|
be reserved by the file sequencer for later write(s) by the
|
||||||
|
<code>write_chunk()</code> API.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-3">checksum_list/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(Yessir, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="checksum_list-4">checksum_list/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>checksum_list(Host, TcpPort, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of chunk checksums for <code>File</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connect-1">connect/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connect(P_srvr) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="connected_p-1">connected_p/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>connected_p(X1) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete_migration-3">delete_migration/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete_migration(Yessir, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="delete_migration-4">delete_migration/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>delete_migration(Host, TcpPort, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Delete a file after it has been successfully
|
||||||
|
migrated.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="disconnect-1">disconnect/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>disconnect(Yessir) -> any()</tt></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-2">get_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(Yessir, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_all_projections-3">get_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_all_projections(Host, TcpPort, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all projections from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epoch-2">get_latest_epoch/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epoch(Sock, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="get_latest_epoch-3">get_latest_epoch/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>get_latest_epoch(Host, TcpPort, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest epoch number + checksum from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-2">list_all_projections/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(Sock, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_all_projections-3">list_all_projections/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_all_projections(Host, TcpPort, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get all epoch numbers from the FLU's projection store.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-2">list_files/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(Yessir, EpochID) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="list_files-3">list_files/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>list_files(Host, TcpPort, EpochID) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the list of all files on the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="quit-1">quit/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>quit(X1) -> any()</tt></p>
|
||||||
|
</div><p>Quit & close the connection to remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-5">read_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(Yessir, EpochID, File, Offset, Size) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_chunk-6">read_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_chunk(Host, TcpPort, EpochID, File, Offset, Size) -> any()</tt></p>
|
||||||
|
</div><p>Read a chunk of data of size <code>Size</code> from <code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-2">read_latest_projection/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(Yessir, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_latest_projection-3">read_latest_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_latest_projection(Host, TcpPort, ProjType) -> any()</tt></p>
|
||||||
|
</div><p>Get the latest projection from the FLU's projection store for <code>ProjType</code></p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-3">read_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(Yessir, ProjType, Epoch) -> any()</tt></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="read_projection-4">read_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>read_projection(Host, TcpPort, ProjType, Epoch) -> any()</tt></p>
|
||||||
|
</div><p>Read a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trunc_hack-3">trunc_hack/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trunc_hack(Yessir, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="trunc_hack-4">trunc_hack/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>trunc_hack(Host, TcpPort, EpochID, File) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Truncate a file after it has been successfully
|
||||||
|
erasure coded.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-1">wedge_status/1</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(Sock) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="wedge_status-2">wedge_status/2</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>wedge_status(Host, TcpPort) -> any()</tt></p>
|
||||||
|
</div><p>Fetch the wedge status from the remote FLU.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-5">write_chunk/5</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(Yessir, EpochID, File, Offset, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_chunk-6">write_chunk/6</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_chunk(Host, TcpPort, EpochID, File, Offset, Chunk) -> any()</tt></p>
|
||||||
|
</div><p>Restricted API: Write a chunk of already-sequenced data to
|
||||||
|
<code>File</code> at <code>Offset</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-3">write_projection/3</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(Yessir, ProjType, Proj) -> any()</tt></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
|
||||||
|
<h3 class="function"><a name="write_projection-4">write_projection/4</a></h3>
|
||||||
|
<div class="spec">
|
||||||
|
<p><tt>write_projection(Host, TcpPort, ProjType, Proj) -> any()</tt></p>
|
||||||
|
</div><p>Write a projection <code>Proj</code> of type <code>ProjType</code>.</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
43
edoc/modules-frame.html
Normal file
43
edoc/modules-frame.html
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The machi application</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<h2 class="indextitle">Modules</h2>
|
||||||
|
<table width="100%" border="0" summary="list of modules">
|
||||||
|
<tr><td><a href="machi_admin_util.html" target="overviewFrame" class="module">machi_admin_util</a></td></tr>
|
||||||
|
<tr><td><a href="machi_app.html" target="overviewFrame" class="module">machi_app</a></td></tr>
|
||||||
|
<tr><td><a href="machi_basho_bench_driver.html" target="overviewFrame" class="module">machi_basho_bench_driver</a></td></tr>
|
||||||
|
<tr><td><a href="machi_chain_manager1.html" target="overviewFrame" class="module">machi_chain_manager1</a></td></tr>
|
||||||
|
<tr><td><a href="machi_chain_repair.html" target="overviewFrame" class="module">machi_chain_repair</a></td></tr>
|
||||||
|
<tr><td><a href="machi_chash.html" target="overviewFrame" class="module">machi_chash</a></td></tr>
|
||||||
|
<tr><td><a href="machi_cinfo.html" target="overviewFrame" class="module">machi_cinfo</a></td></tr>
|
||||||
|
<tr><td><a href="machi_config.html" target="overviewFrame" class="module">machi_config</a></td></tr>
|
||||||
|
<tr><td><a href="machi_cr_client.html" target="overviewFrame" class="module">machi_cr_client</a></td></tr>
|
||||||
|
<tr><td><a href="machi_csum_table.html" target="overviewFrame" class="module">machi_csum_table</a></td></tr>
|
||||||
|
<tr><td><a href="machi_dt.html" target="overviewFrame" class="module">machi_dt</a></td></tr>
|
||||||
|
<tr><td><a href="machi_file_proxy.html" target="overviewFrame" class="module">machi_file_proxy</a></td></tr>
|
||||||
|
<tr><td><a href="machi_file_proxy_sup.html" target="overviewFrame" class="module">machi_file_proxy_sup</a></td></tr>
|
||||||
|
<tr><td><a href="machi_fitness.html" target="overviewFrame" class="module">machi_fitness</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu1.html" target="overviewFrame" class="module">machi_flu1</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu1_client.html" target="overviewFrame" class="module">machi_flu1_client</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu_filename_mgr.html" target="overviewFrame" class="module">machi_flu_filename_mgr</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu_metadata_mgr.html" target="overviewFrame" class="module">machi_flu_metadata_mgr</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu_metadata_mgr_sup.html" target="overviewFrame" class="module">machi_flu_metadata_mgr_sup</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu_psup.html" target="overviewFrame" class="module">machi_flu_psup</a></td></tr>
|
||||||
|
<tr><td><a href="machi_flu_sup.html" target="overviewFrame" class="module">machi_flu_sup</a></td></tr>
|
||||||
|
<tr><td><a href="machi_lifecycle_mgr.html" target="overviewFrame" class="module">machi_lifecycle_mgr</a></td></tr>
|
||||||
|
<tr><td><a href="machi_merkle_tree.html" target="overviewFrame" class="module">machi_merkle_tree</a></td></tr>
|
||||||
|
<tr><td><a href="machi_pb_high_client.html" target="overviewFrame" class="module">machi_pb_high_client</a></td></tr>
|
||||||
|
<tr><td><a href="machi_pb_translate.html" target="overviewFrame" class="module">machi_pb_translate</a></td></tr>
|
||||||
|
<tr><td><a href="machi_plist.html" target="overviewFrame" class="module">machi_plist</a></td></tr>
|
||||||
|
<tr><td><a href="machi_projection.html" target="overviewFrame" class="module">machi_projection</a></td></tr>
|
||||||
|
<tr><td><a href="machi_projection_store.html" target="overviewFrame" class="module">machi_projection_store</a></td></tr>
|
||||||
|
<tr><td><a href="machi_proxy_flu1_client.html" target="overviewFrame" class="module">machi_proxy_flu1_client</a></td></tr>
|
||||||
|
<tr><td><a href="machi_sup.html" target="overviewFrame" class="module">machi_sup</a></td></tr>
|
||||||
|
<tr><td><a href="machi_util.html" target="overviewFrame" class="module">machi_util</a></td></tr>
|
||||||
|
<tr><td><a href="machi_yessir_client.html" target="overviewFrame" class="module">machi_yessir_client</a></td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
185
edoc/overview-summary.html
Normal file
185
edoc/overview-summary.html
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Machi: a small village of replicated files
|
||||||
|
</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<h1>Machi: a small village of replicated files
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<h3><a name="About_This_EDoc_Documentation">About This EDoc Documentation</a></h3>
|
||||||
|
|
||||||
|
<p>This EDoc-style documentation will concern itself only with Erlang
|
||||||
|
function APIs and function & data types. Higher-level design and
|
||||||
|
commentary will remain outside of the Erlang EDoc system; please see
|
||||||
|
the "Pointers to Other Machi Documentation" section below for more
|
||||||
|
details.</p>
|
||||||
|
|
||||||
|
<p>Readers should beware that this documentation may be out-of-sync with
|
||||||
|
the source code. When in doubt, use the <code>make edoc</code> command to
|
||||||
|
regenerate all HTML pages.</p>
|
||||||
|
|
||||||
|
<p>It is the developer's responsibility to re-generate the documentation
|
||||||
|
periodically and commit it to the Git repo.</p>
|
||||||
|
|
||||||
|
<h3><a name="Machi_Code_Overview">Machi Code Overview</a></h3>
|
||||||
|
|
||||||
|
<h4><a name="Chain_Manager">Chain Manager</a></h4>
|
||||||
|
|
||||||
|
<p>The Chain Manager is responsible for managing the state of Machi's
|
||||||
|
"Chain Replication" state. This role is roughly analogous to the
|
||||||
|
"Riak Core" application inside of Riak, which takes care of
|
||||||
|
coordinating replica placement and replica repair.</p>
|
||||||
|
|
||||||
|
<p>For each primitive data server in the cluster, a Machi FLU, there is a
|
||||||
|
Chain Manager process that manages its FLU's role within the Machi
|
||||||
|
cluster's Chain Replication scheme. Each Chain Manager process
|
||||||
|
executes locally and independently to manage the distributed state of
|
||||||
|
a single Machi Chain Replication chain.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li><p> To contrast with Riak Core ... Riak Core's claimant process is
|
||||||
|
solely responsible for managing certain critical aspects of
|
||||||
|
Riak Core distributed state. Machi's Chain Manager process
|
||||||
|
performs similar tasks as Riak Core's claimant. However, Machi
|
||||||
|
has several active Chain Manager processes, one per FLU server,
|
||||||
|
instead of a single active process like Core's claimant. Each
|
||||||
|
Chain Manager process acts independently; each is constrained
|
||||||
|
so that it will reach consensus via independent computation
|
||||||
|
& action.</p>
|
||||||
|
|
||||||
|
Full discussion of this distributed consensus is outside the
|
||||||
|
scope of this document; see the "Pointers to Other Machi
|
||||||
|
Documentation" section below for more information.
|
||||||
|
</li>
|
||||||
|
<li> Machi differs from a Riak Core application because Machi's
|
||||||
|
replica placement policy is simply, "All Machi servers store
|
||||||
|
replicas of all Machi files".
|
||||||
|
Machi is intended to be a primitive building block for creating larger
|
||||||
|
cluster-of-clusters where files are
|
||||||
|
distributed/fragmented/sharded across a large pool of
|
||||||
|
independent Machi clusters.
|
||||||
|
</li>
|
||||||
|
<li> See
|
||||||
|
<a href="https://www.usenix.org/legacy/events/osdi04/tech/renesse.html" target="_top"><tt>https://www.usenix.org/legacy/events/osdi04/tech/renesse.html</tt></a>
|
||||||
|
for a copy of the paper, "Chain Replication for Supporting High
|
||||||
|
Throughput and Availability" by Robbert van Renesse and Fred
|
||||||
|
B. Schneider.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4><a name="FLU">FLU</a></h4>
|
||||||
|
|
||||||
|
<p>The FLU is the basic storage server for Machi.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> The name FLU is taken from "flash storage unit" from the paper
|
||||||
|
"CORFU: A Shared Log Design for Flash Clusters" by
|
||||||
|
Balakrishnan, Malkhi, Prabhakaran, and Wobber. See
|
||||||
|
<a href="https://www.usenix.org/conference/nsdi12/technical-sessions/presentation/balakrishnan" target="_top"><tt>https://www.usenix.org/conference/nsdi12/technical-sessions/presentation/balakrishnan</tt></a>
|
||||||
|
</li>
|
||||||
|
<li> In CORFU, the sequencer step is a prerequisite step that is
|
||||||
|
performed by a separate component, the Sequencer.
|
||||||
|
In Machi, the <code>append_chunk()</code> protocol message has
|
||||||
|
an implicit "sequencer" operation applied by the "head" of the
|
||||||
|
Machi Chain Replication chain. If a client wishes to write
|
||||||
|
data that has already been assigned a sequencer position, then
|
||||||
|
the <code>write_chunk()</code> API function is used.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>For each FLU, there are three independent tasks that are implemented
|
||||||
|
using three different Erlang processes:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> A FLU server, implemented primarily by <code>machi_flu.erl</code>.
|
||||||
|
</li>
|
||||||
|
<li> A projection store server, implemented primarily by
|
||||||
|
<code>machi_projection_store.erl</code>.
|
||||||
|
</li>
|
||||||
|
<li> A chain state manager server, implemented primarily by
|
||||||
|
<code>machi_chain_manager1.erl</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>From the perspective of failure detection, it is very convenient that
|
||||||
|
all three FLU-related services (file server, sequencer server, and
|
||||||
|
projection server) are accessed using the same single TCP port.</p>
|
||||||
|
|
||||||
|
<h4><a name="Projection_(data_structure)">Projection (data structure)</a></h4>
|
||||||
|
|
||||||
|
<p>The projection is a data structure that specifies the current state
|
||||||
|
of the Machi cluster: all FLUs, which FLUS are considered
|
||||||
|
up/running or down/crashed/stopped, which FLUs are actively
|
||||||
|
participants in the Chain Replication protocol, and which FLUs are
|
||||||
|
under "repair" (i.e., having their data resyncronized when
|
||||||
|
newly-added to a cluster or when restarting after a crash).</p>
|
||||||
|
|
||||||
|
<h4><a name="Projection_Store_(server)">Projection Store (server)</a></h4>
|
||||||
|
|
||||||
|
<p>The projection store is a storage service that is implemented by an
|
||||||
|
Erlang/OTP <code>gen_server</code> process that is associated with each
|
||||||
|
FLU. Conceptually, the projection store is an array of
|
||||||
|
write-once registers. For each projection store register, the
|
||||||
|
key is a 2-tuple of an epoch number (<code>non_neg_integer()</code> type)
|
||||||
|
and a projection type (<code>public</code> or <code>private</code> type); the value is
|
||||||
|
a projection data structure (<code>projection_v1()</code> type).</p>
|
||||||
|
|
||||||
|
<h4><a name="Client_and_Proxy_Client">Client and Proxy Client</a></h4>
|
||||||
|
|
||||||
|
<p>Machi is intentionally avoiding using distributed Erlang for Machi's
|
||||||
|
communication. This design decision makes Erlang-side code more
|
||||||
|
difficult & complex but allows us the freedom of implementing
|
||||||
|
parts of Machi in other languages without major
|
||||||
|
protocol&API&glue code changes later in the product's
|
||||||
|
lifetime.</p>
|
||||||
|
|
||||||
|
<p>There are two layers of interface for Machi clients.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> The <code>machi_flu1_client</code> module implements an API that uses a
|
||||||
|
TCP socket directly.
|
||||||
|
</li>
|
||||||
|
<li> The <code>machi_proxy_flu1_client</code> module implements an API that
|
||||||
|
uses a local, long-lived <code>gen_server</code> process as a proxy for
|
||||||
|
the remote, perhaps disconnected-or-crashed Machi FLU server.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The types for both modules ought to be the same. However, due to
|
||||||
|
rapid code churn, some differences might exist. Any major difference
|
||||||
|
is (almost by definition) a bug: please open a GitHub issue to request
|
||||||
|
a correction.</p>
|
||||||
|
|
||||||
|
<h3><a name="TODO_notes">TODO notes</a></h3>
|
||||||
|
|
||||||
|
<p>Any use of the string "TODO" in upper/lower/mixed case, anywhere in
|
||||||
|
the code, is a reminder signal of unfinished work.</p>
|
||||||
|
|
||||||
|
<h3><a name="Pointers_to_Other_Machi_Documentation">Pointers to Other Machi Documentation</a></h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li> If you are viewing this document locally, please look in the
|
||||||
|
<code>../doc/</code> directory,
|
||||||
|
</li>
|
||||||
|
<li> If you are viewing this document via the Web, please find the
|
||||||
|
documentation via this link:
|
||||||
|
<a href="http://github.com/basho/machi/tree/master/doc/" target="_top"><tt>http://github.com/basho/machi/tree/master/doc/</tt></a>
|
||||||
|
Please be aware that this link points to the <code>master</code> branch
|
||||||
|
of the Machi source repository and therefore may be
|
||||||
|
out-of-sync with non-<code>master</code> branch code.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
|
||||||
|
<p><i>Generated by EDoc, Dec 8 2015, 21:37:38.</i></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
14
edoc/overview.edoc
Normal file
14
edoc/overview.edoc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
@title Machi: a small village of replicated files
|
||||||
|
|
||||||
|
@doc
|
||||||
|
|
||||||
|
Documentation for Machi is an ongoing challenge. Much of the
|
||||||
|
high-level design & commentary are outside of the Erlang EDoc system
|
||||||
|
|
||||||
|
Zoom2 zoom zoom zoom boom boom boom boom
|
||||||
|
|
||||||
|
Rumba tango Rumba tango Rumba tango Rumba tango Rumba tango Rumba
|
||||||
|
tango Rumba tango Rumba tango Rumba tango Rumba tango Rumba tango
|
||||||
|
Rumba tango Rumba tango Rumba tango Rumba tango Rumba tango Rumba
|
||||||
|
tango Rumba tango Rumba tango Rumba tango Rumba tango
|
11
edoc/packages-frame.html
Normal file
11
edoc/packages-frame.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The machi application</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white">
|
||||||
|
<h2 class="indextitle">Packages</h2>
|
||||||
|
<table width="100%" border="0" summary="list of packages"></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
55
edoc/stylesheet.css
Normal file
55
edoc/stylesheet.css
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* standard EDoc style sheet */
|
||||||
|
body {
|
||||||
|
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||||
|
margin-left: .25in;
|
||||||
|
margin-right: .2in;
|
||||||
|
margin-top: 0.2in;
|
||||||
|
margin-bottom: 0.2in;
|
||||||
|
color: #000000;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
h1,h2 {
|
||||||
|
margin-left: -0.2in;
|
||||||
|
}
|
||||||
|
div.navbar {
|
||||||
|
background-color: #add8e6;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
h2.indextitle {
|
||||||
|
padding: 0.4em;
|
||||||
|
background-color: #add8e6;
|
||||||
|
}
|
||||||
|
h3.function,h3.typedecl {
|
||||||
|
background-color: #add8e6;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
div.spec {
|
||||||
|
margin-left: 2em;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
a.module,a.package {
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
a.module:hover,a.package:hover {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
ul.definitions {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
ul.index {
|
||||||
|
list-style-type: none;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minor style tweaks
|
||||||
|
*/
|
||||||
|
ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 3
|
||||||
|
}
|
BIN
images/basho_bench.example0.png
Normal file
BIN
images/basho_bench.example0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 269 KiB |
BIN
images/supervisor-2flus.png
Normal file
BIN
images/supervisor-2flus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -1,63 +0,0 @@
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
%%
|
|
||||||
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% This file is provided to you under the Apache License,
|
|
||||||
%% Version 2.0 (the "License"); you may not use this file
|
|
||||||
%% except in compliance with the License. You may obtain
|
|
||||||
%% a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing,
|
|
||||||
%% software distributed under the License is distributed on an
|
|
||||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
%% KIND, either express or implied. See the License for the
|
|
||||||
%% specific language governing permissions and limitations
|
|
||||||
%% under the License.
|
|
||||||
%%
|
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
|
|
||||||
%% @doc Now 4GiBytes, could be up to 64bit due to PB message limit of
|
|
||||||
%% chunk size
|
|
||||||
-define(DEFAULT_MAX_FILE_SIZE, ((1 bsl 32) - 1)).
|
|
||||||
-define(MINIMUM_OFFSET, 1024).
|
|
||||||
|
|
||||||
%% 0th draft of checksum typing with 1st byte.
|
|
||||||
-define(CSUM_TAG_NONE, 0). % No csum provided by client
|
|
||||||
-define(CSUM_TAG_CLIENT_SHA, 1). % Client-generated SHA1
|
|
||||||
-define(CSUM_TAG_SERVER_SHA, 2). % Server-genereated SHA1
|
|
||||||
-define(CSUM_TAG_SERVER_REGEN_SHA, 3). % Server-regenerated SHA1
|
|
||||||
|
|
||||||
-define(CSUM_TAG_NONE_ATOM, none).
|
|
||||||
-define(CSUM_TAG_CLIENT_SHA_ATOM, client_sha).
|
|
||||||
-define(CSUM_TAG_SERVER_SHA_ATOM, server_sha).
|
|
||||||
-define(CSUM_TAG_SERVER_REGEN_SHA_ATOM, server_regen_sha).
|
|
||||||
|
|
||||||
%% Protocol Buffers goop
|
|
||||||
-define(PB_MAX_MSG_SIZE, (33*1024*1024)).
|
|
||||||
-define(PB_PACKET_OPTS, [{packet, 4}, {packet_size, ?PB_MAX_MSG_SIZE}]).
|
|
||||||
|
|
||||||
%% TODO: it's used in flu_sup and elsewhere, change this to suitable name
|
|
||||||
-define(TEST_ETS_TABLE, test_ets_table).
|
|
||||||
|
|
||||||
-define(DEFAULT_COC_NAMESPACE, "").
|
|
||||||
-define(DEFAULT_COC_LOCATOR, 0).
|
|
||||||
|
|
||||||
-record(ns_info, {
|
|
||||||
version = 0 :: machi_dt:namespace_version(),
|
|
||||||
name = <<>> :: machi_dt:namespace(),
|
|
||||||
locator = 0 :: machi_dt:locator()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(append_opts, {
|
|
||||||
chunk_extra = 0 :: machi_dt:chunk_size(),
|
|
||||||
preferred_file_name :: 'undefined' | machi_dt:file_name_s(),
|
|
||||||
flag_fail_preferred = false :: boolean()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(read_opts, {
|
|
||||||
no_checksum = false :: boolean(),
|
|
||||||
no_chunk = false :: boolean(),
|
|
||||||
needs_trimmed = false :: boolean()
|
|
||||||
}).
|
|
|
@ -1,26 +0,0 @@
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
%%
|
|
||||||
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% This file is provided to you under the Apache License,
|
|
||||||
%% Version 2.0 (the "License"); you may not use this file
|
|
||||||
%% except in compliance with the License. You may obtain
|
|
||||||
%% a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing,
|
|
||||||
%% software distributed under the License is distributed on an
|
|
||||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
%% KIND, either express or implied. See the License for the
|
|
||||||
%% specific language governing permissions and limitations
|
|
||||||
%% under the License.
|
|
||||||
%%
|
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
|
|
||||||
-include("machi_projection.hrl").
|
|
||||||
|
|
||||||
-define(NOT_FLAPPING, {0,0,0}).
|
|
||||||
|
|
||||||
-type projection() :: #projection_v1{}.
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
%% machi merkle tree records
|
|
||||||
|
|
||||||
-record(naive, {
|
|
||||||
chunk_size = 1048576 :: pos_integer(), %% default 1 MB
|
|
||||||
recalc = true :: boolean(),
|
|
||||||
root :: 'undefined' | binary(),
|
|
||||||
lvl1 = [] :: [ binary() ],
|
|
||||||
lvl2 = [] :: [ binary() ],
|
|
||||||
lvl3 = [] :: [ binary() ],
|
|
||||||
leaves = [] :: [ { Offset :: pos_integer(),
|
|
||||||
Size :: pos_integer(),
|
|
||||||
Csum :: binary()} ]
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(mt, {
|
|
||||||
filename :: string(),
|
|
||||||
tree :: #naive{},
|
|
||||||
backend = 'naive' :: 'naive'
|
|
||||||
}).
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
%%
|
|
||||||
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% This file is provided to you under the Apache License,
|
|
||||||
%% Version 2.0 (the "License"); you may not use this file
|
|
||||||
%% except in compliance with the License. You may obtain
|
|
||||||
%% a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing,
|
|
||||||
%% software distributed under the License is distributed on an
|
|
||||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
%% KIND, either express or implied. See the License for the
|
|
||||||
%% specific language governing permissions and limitations
|
|
||||||
%% under the License.
|
|
||||||
%%
|
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
|
|
||||||
-ifndef(MACHI_PROJECTION_HRL).
|
|
||||||
-define(MACHI_PROJECTION_HRL, true).
|
|
||||||
|
|
||||||
-type pv1_consistency_mode() :: 'ap_mode' | 'cp_mode'.
|
|
||||||
-type pv1_chain_name():: atom().
|
|
||||||
-type pv1_csum() :: binary().
|
|
||||||
-type pv1_epoch() :: {pv1_epoch_n(), pv1_csum()}.
|
|
||||||
-type pv1_epoch_n() :: non_neg_integer().
|
|
||||||
-type pv1_server() :: atom().
|
|
||||||
-type pv1_timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
|
|
||||||
|
|
||||||
-record(p_srvr, {
|
|
||||||
name :: pv1_server(),
|
|
||||||
proto_mod = 'machi_flu1_client' :: atom(), % Module name
|
|
||||||
address :: term(), % Protocol-specific
|
|
||||||
port :: term(), % Protocol-specific
|
|
||||||
props = [] :: list() % proplist for other related info
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(flap_i, {
|
|
||||||
flap_count :: {term(), term()},
|
|
||||||
all_hosed :: list(),
|
|
||||||
all_flap_counts :: list(),
|
|
||||||
my_unique_prop_count :: non_neg_integer()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-type p_srvr() :: #p_srvr{}.
|
|
||||||
-type p_srvr_dict() :: orddict:orddict().
|
|
||||||
|
|
||||||
-define(DUMMY_PV1_EPOCH, {0,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}).
|
|
||||||
|
|
||||||
%% Kludge for spam gossip. TODO: replace me
|
|
||||||
-define(SPAM_PROJ_EPOCH, ((1 bsl 32) - 7)).
|
|
||||||
|
|
||||||
-record(projection_v1, {
|
|
||||||
epoch_number :: pv1_epoch_n() | ?SPAM_PROJ_EPOCH,
|
|
||||||
epoch_csum :: pv1_csum(),
|
|
||||||
author_server :: pv1_server(),
|
|
||||||
chain_name = ch_not_def_yet :: pv1_chain_name(),
|
|
||||||
all_members :: [pv1_server()],
|
|
||||||
witnesses = [] :: [pv1_server()],
|
|
||||||
creation_time :: pv1_timestamp(),
|
|
||||||
mode = ap_mode :: pv1_consistency_mode(),
|
|
||||||
upi :: [pv1_server()],
|
|
||||||
repairing :: [pv1_server()],
|
|
||||||
down :: [pv1_server()],
|
|
||||||
dbg :: list(), %proplist(), is checksummed
|
|
||||||
dbg2 :: list(), %proplist(), is not checksummed
|
|
||||||
members_dict :: p_srvr_dict()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-define(MACHI_DEFAULT_TCP_PORT, 50000).
|
|
||||||
|
|
||||||
-define(SHA_MAX, (1 bsl (20*8))).
|
|
||||||
|
|
||||||
%% Set a limit to the maximum chain length, so that it's easier to
|
|
||||||
%% create a consistent projection ranking score.
|
|
||||||
-define(MAX_CHAIN_LENGTH, 64).
|
|
||||||
|
|
||||||
-record(chain_def_v1, {
|
|
||||||
name :: atom(), % chain name
|
|
||||||
mode :: pv1_consistency_mode(),
|
|
||||||
full = [] :: [p_srvr()],
|
|
||||||
witnesses = [] :: [p_srvr()],
|
|
||||||
old_full = [] :: [pv1_server()], % guard against some races
|
|
||||||
old_witnesses=[] :: [pv1_server()], % guard against some races
|
|
||||||
local_run = [] :: [pv1_server()], % must be tailored to each machine!
|
|
||||||
local_stop = [] :: [pv1_server()], % must be tailored to each machine!
|
|
||||||
props = [] :: list() % proplist for other related info
|
|
||||||
}).
|
|
||||||
|
|
||||||
-endif. % !MACHI_PROJECTION_HRL
|
|
|
@ -1,31 +0,0 @@
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
%%
|
|
||||||
%% Machi: a small village of replicated files
|
|
||||||
%%
|
|
||||||
%% Copyright (c) 2014-2015 Basho Technologies, Inc. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% This file is provided to you under the Apache License,
|
|
||||||
%% Version 2.0 (the "License"); you may not use this file
|
|
||||||
%% except in compliance with the License. You may obtain
|
|
||||||
%% a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing,
|
|
||||||
%% software distributed under the License is distributed on an
|
|
||||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
%% KIND, either express or implied. See the License for the
|
|
||||||
%% specific language governing permissions and limitations
|
|
||||||
%% under the License.
|
|
||||||
%%
|
|
||||||
%% -------------------------------------------------------------------
|
|
||||||
|
|
||||||
-ifdef(PULSE).
|
|
||||||
-define(V(Fmt, Args), pulse:format(Fmt, Args)).
|
|
||||||
-else. % PULSE
|
|
||||||
-define(V(Fmt, Args), io:format(user, Fmt, Args)).
|
|
||||||
-endif. % PULSE
|
|
||||||
|
|
||||||
-define(D(X), ?V("~s ~p\n", [??X, X])).
|
|
||||||
-define(Dw(X), ?V("~s ~w\n", [??X, X])).
|
|
||||||
|
|
38
index.html
Normal file
38
index.html
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Machi by basho</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section class="page-header">
|
||||||
|
<h1 class="project-name">Machi</h1>
|
||||||
|
<h2 class="project-tagline">Machi file store: developer API</h2>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="main-content">
|
||||||
|
<p> <a href="edoc/">For a snapshot view of the HTML "EDoc" documentation for Machi, please follow this EDoc Link</a>.</p>
|
||||||
|
<p> <a href="https://github.com/basho/machi/tree/master/doc/">All other Machi documentation.</a></p>
|
||||||
|
<p> <a href="https://github.com/basho/machi">View README & source on GitHub</a>
|
||||||
|
<p> <a href="https://github.com/basho/machi/zipball/master">Download
|
||||||
|
source as a ZIP file</a>
|
||||||
|
<p> <a href="https://github.com/basho/machi/tarball/master">Download
|
||||||
|
source as a compressed TAR file</a>
|
||||||
|
|
||||||
|
<footer class="site-footer">
|
||||||
|
<span class="site-footer-owner"><a href="https://github.com/basho/machi">Machi</a> is maintained by <a href="https://github.com/basho">basho</a>.</span>
|
||||||
|
|
||||||
|
<span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
1
params.json
Normal file
1
params.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"name":"Machi","tagline":"Machi file store: developer API","body":"For a snapshot view of the HTML \"EDoc\" documentation for Machi, please follow the [EDoc Link](edoc/).","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}
|
|
@ -1,45 +0,0 @@
|
||||||
%% Mandatory: adjust this code path to top of your compiled Machi source distro
|
|
||||||
{code_paths, ["/Users/fritchie/b/src/machi"]}.
|
|
||||||
{driver, machi_basho_bench_driver}.
|
|
||||||
|
|
||||||
%% Chose your maximum rate (per worker proc, see 'concurrent' below)
|
|
||||||
%{mode, {rate,10}}.
|
|
||||||
%{mode, {rate,20}}.
|
|
||||||
{mode, max}.
|
|
||||||
|
|
||||||
%% Runtime & reporting interval
|
|
||||||
{duration, 10}. % minutes
|
|
||||||
{report_interval, 1}. % seconds
|
|
||||||
|
|
||||||
%% Choose your number of worker procs
|
|
||||||
%{concurrent, 1}.
|
|
||||||
{concurrent, 5}.
|
|
||||||
%{concurrent, 10}.
|
|
||||||
|
|
||||||
%% Here's a chain of (up to) length 3, all on localhost
|
|
||||||
%% Note: if any servers are down, and your OS/TCP stack has an
|
|
||||||
%% ICMP response limit such as OS X's "net.inet.icmp.icmplim" setting,
|
|
||||||
%% then if that setting is very low (e.g., OS X's limit is 50), then
|
|
||||||
%% you can have big problems with ICMP/RST responses being delayed and
|
|
||||||
%% interactive *very* badly with your test.
|
|
||||||
%% For OS X, fix using "sudo sysctl -w net.inet.icmp.icmplim=9999"
|
|
||||||
{machi_server_info,
|
|
||||||
[
|
|
||||||
{p_srvr,a,machi_flu1_client,"localhost",4444,[]},
|
|
||||||
{p_srvr,b,machi_flu1_client,"localhost",4445,[]},
|
|
||||||
{p_srvr,c,machi_flu1_client,"localhost",4446,[]}
|
|
||||||
]}.
|
|
||||||
{machi_ets_key_tab_type, set}. % set | ordered_set
|
|
||||||
|
|
||||||
%% Workload-specific definitions follow....
|
|
||||||
|
|
||||||
%% 10 parts 'append' operation + 0 parts anything else = 100% 'append' ops
|
|
||||||
{operations, [{append, 10}]}.
|
|
||||||
|
|
||||||
%% For append, key = Machi file prefix name
|
|
||||||
{key_generator, {to_binstr, "prefix~w", {uniform_int, 30}}}.
|
|
||||||
|
|
||||||
%% Increase size of value_generator_source_size if value_generator is big!!
|
|
||||||
{value_generator_source_size, 2111000}.
|
|
||||||
{value_generator, {fixed_bin, 32768}}. % 32 KB
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
%% Mandatory: adjust this code path to top of your compiled Machi source distro
|
|
||||||
{code_paths, ["/Users/fritchie/b/src/machi"]}.
|
|
||||||
{driver, machi_basho_bench_driver}.
|
|
||||||
|
|
||||||
%% Chose your maximum rate (per worker proc, see 'concurrent' below)
|
|
||||||
%{mode, {rate,10}}.
|
|
||||||
%{mode, {rate,20}}.
|
|
||||||
{mode, max}.
|
|
||||||
|
|
||||||
%% Runtime & reporting interval
|
|
||||||
{duration, 10}. % minutes
|
|
||||||
{report_interval, 1}. % seconds
|
|
||||||
|
|
||||||
%% Choose your number of worker procs
|
|
||||||
%{concurrent, 1}.
|
|
||||||
{concurrent, 5}.
|
|
||||||
%{concurrent, 10}.
|
|
||||||
|
|
||||||
%% Here's a chain of (up to) length 3, all on localhost
|
|
||||||
%% Note: if any servers are down, and your OS/TCP stack has an
|
|
||||||
%% ICMP response limit such as OS X's "net.inet.icmp.icmplim" setting,
|
|
||||||
%% then if that setting is very low (e.g., OS X's limit is 50), then
|
|
||||||
%% you can have big problems with ICMP/RST responses being delayed and
|
|
||||||
%% interactive *very* badly with your test.
|
|
||||||
%% For OS X, fix using "sudo sysctl -w net.inet.icmp.icmplim=9999"
|
|
||||||
{machi_server_info,
|
|
||||||
[
|
|
||||||
{p_srvr,a,machi_flu1_client,"localhost",4444,[]},
|
|
||||||
{p_srvr,b,machi_flu1_client,"localhost",4445,[]},
|
|
||||||
{p_srvr,c,machi_flu1_client,"localhost",4446,[]}
|
|
||||||
]}.
|
|
||||||
{machi_ets_key_tab_type, set}. % set | ordered_set
|
|
||||||
|
|
||||||
%% Workload-specific definitions follow....
|
|
||||||
|
|
||||||
%% 10 parts 'read' operation + 0 parts anything else = 100% 'read' ops
|
|
||||||
{operations, [{read, 10}]}.
|
|
||||||
|
|
||||||
%% For read, key = integer index into Machi's chunk ETS table, modulo the
|
|
||||||
%% ETS table size, so a huge number here is OK.
|
|
||||||
{key_generator, {uniform_int, 999999999999}}.
|
|
||||||
|
|
||||||
%% For read, value_generator_* isn't used, so leave these defaults as-is.
|
|
||||||
{value_generator_source_size, 2111000}.
|
|
||||||
{value_generator, {fixed_bin, 32768}}. % 32 KB
|
|
||||||
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo "Step: Verify that the required entries in /etc/hosts are present"
|
|
||||||
for i in 1 2 3; do
|
|
||||||
grep machi$i /etc/hosts | egrep -s '^127.0.0.1' > /dev/null 2>&1
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "'grep -s machi$i' failed. Aborting, sorry."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
ping -c 1 machi$i > /dev/null 2>&1
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "Ping attempt on host machi$i failed. Aborting."
|
|
||||||
echo ""
|
|
||||||
ping -c 1 machi$i
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Step: add a verbose logging option to app.config"
|
|
||||||
for i in 1 2 3; do
|
|
||||||
ed ./dev/dev$i/etc/app.config <<EOF > /dev/null 2>&1
|
|
||||||
/verbose_confirm
|
|
||||||
a
|
|
||||||
{chain_manager_opts, [{private_write_verbose_confirm,true}]},
|
|
||||||
{stability_time, 1},
|
|
||||||
.
|
|
||||||
w
|
|
||||||
q
|
|
||||||
EOF
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Step: start three three Machi application instances"
|
|
||||||
for i in 1 2 3; do
|
|
||||||
./dev/dev$i/bin/machi start
|
|
||||||
./dev/dev$i/bin/machi ping
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Sorry, a 'ping' check for instance dev$i failed. Aborting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Step: configure one chain to start a Humming Consensus group with three members"
|
|
||||||
|
|
||||||
# Note: $CWD of each Machi proc is two levels below the source code root dir.
|
|
||||||
LIFECYCLE000=../../priv/quick-admin-examples/demo-000
|
|
||||||
for i in 3 2 1; do
|
|
||||||
./dev/dev$i/bin/machi-admin quick-admin-apply $LIFECYCLE000 machi$i
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Sorry, 'machi-admin quick-admin-apply failed' on machi$i. Aborting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exit 0
|
|
93
priv/humming-consensus-demo.vagrant/Vagrantfile
vendored
93
priv/humming-consensus-demo.vagrant/Vagrantfile
vendored
|
@ -1,93 +0,0 @@
|
||||||
# -*- mode: ruby -*-
|
|
||||||
# vi: set ft=ruby :
|
|
||||||
|
|
||||||
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
|
||||||
# configures the configuration version (we support older styles for
|
|
||||||
# backwards compatibility). Please don't change it unless you know what
|
|
||||||
# you're doing.
|
|
||||||
Vagrant.configure(2) do |config|
|
|
||||||
# The most common configuration options are documented and commented below.
|
|
||||||
# For a complete reference, please see the online documentation at
|
|
||||||
# https://docs.vagrantup.com.
|
|
||||||
|
|
||||||
# Every Vagrant development environment requires a box. You can search for
|
|
||||||
# boxes at https://atlas.hashicorp.com/search.
|
|
||||||
# If this Vagrant box has not been downloaded before (e.g. using "vagrant box add"),
|
|
||||||
# then Vagrant will automatically download the VM image from HashiCorp.
|
|
||||||
config.vm.box = "hashicorp/precise64"
|
|
||||||
# If using a FreeBSD box, Bash may not be installed.
|
|
||||||
# Use the config.ssh.shell setting to specify an alternate shell.
|
|
||||||
# Note, however, that any code in the 'config.vm.provision' section
|
|
||||||
# would then have to use this shell's syntax!
|
|
||||||
# config.ssh.shell = "/bin/csh -l"
|
|
||||||
|
|
||||||
# Disable automatic box update checking. If you disable this, then
|
|
||||||
# boxes will only be checked for updates when the user runs
|
|
||||||
# `vagrant box outdated`. This is not recommended.
|
|
||||||
# config.vm.box_check_update = false
|
|
||||||
|
|
||||||
# Create a forwarded port mapping which allows access to a specific port
|
|
||||||
# within the machine from a port on the host machine. In the example below,
|
|
||||||
# accessing "localhost:8080" will access port 80 on the guest machine.
|
|
||||||
# config.vm.network "forwarded_port", guest: 80, host: 8080
|
|
||||||
|
|
||||||
# Create a private network, which allows host-only access to the machine
|
|
||||||
# using a specific IP.
|
|
||||||
# config.vm.network "private_network", ip: "192.168.33.10"
|
|
||||||
|
|
||||||
# Create a public network, which generally matched to bridged network.
|
|
||||||
# Bridged networks make the machine appear as another physical device on
|
|
||||||
# your network.
|
|
||||||
# config.vm.network "public_network"
|
|
||||||
|
|
||||||
# Share an additional folder to the guest VM. The first argument is
|
|
||||||
# the path on the host to the actual folder. The second argument is
|
|
||||||
# the path on the guest to mount the folder. And the optional third
|
|
||||||
# argument is a set of non-required options.
|
|
||||||
# config.vm.synced_folder "../data", "/vagrant_data"
|
|
||||||
|
|
||||||
# Provider-specific configuration so you can fine-tune various
|
|
||||||
# backing providers for Vagrant. These expose provider-specific options.
|
|
||||||
# Example for VirtualBox:
|
|
||||||
#
|
|
||||||
config.vm.provider "virtualbox" do |vb|
|
|
||||||
# Display the VirtualBox GUI when booting the machine
|
|
||||||
# vb.gui = true
|
|
||||||
|
|
||||||
# Customize the amount of memory on the VM:
|
|
||||||
vb.memory = "512"
|
|
||||||
end
|
|
||||||
#
|
|
||||||
# View the documentation for the provider you are using for more
|
|
||||||
# information on available options.
|
|
||||||
|
|
||||||
# Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
|
|
||||||
# such as FTP and Heroku are also available. See the documentation at
|
|
||||||
# https://docs.vagrantup.com/v2/push/atlas.html for more information.
|
|
||||||
# config.push.define "atlas" do |push|
|
|
||||||
# push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
|
|
||||||
# end
|
|
||||||
|
|
||||||
# Enable provisioning with a shell script. Additional provisioners such as
|
|
||||||
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
|
||||||
# documentation for more information about their specific syntax and use.
|
|
||||||
config.vm.provision "shell", inline: <<-SHELL
|
|
||||||
# Install prerequsites
|
|
||||||
# Support here for FreeBSD is experimental
|
|
||||||
apt-get update ; sudo apt-get install -y git sudo rsync ; # Ubuntu Linux
|
|
||||||
env ASSUME_ALWAYS_YES=yes pkg install -f git sudo rsync ; # FreeBSD 10
|
|
||||||
|
|
||||||
# Install dependent packages, using slf-configurator
|
|
||||||
git clone https://github.com/slfritchie/slf-configurator.git
|
|
||||||
chown -R vagrant ./slf-configurator
|
|
||||||
(cd slf-configurator ; sudo sh -x ./ALL.sh)
|
|
||||||
echo 'export PATH=${PATH}:/usr/local/erlang/17.5/bin' >> ~vagrant/.bashrc
|
|
||||||
export PATH=${PATH}:/usr/local/erlang/17.5/bin
|
|
||||||
## echo 'set path = ( $path /usr/local/erlang/17.5/bin )' >> ~vagrant/.cshrc
|
|
||||||
## setenv PATH /usr/local/erlang/17.5/bin:$PATH
|
|
||||||
|
|
||||||
git clone https://github.com/basho/machi.git
|
|
||||||
(cd machi ; git checkout master ; make && make test )
|
|
||||||
chown -R vagrant ./machi
|
|
||||||
SHELL
|
|
||||||
end
|
|
|
@ -1,81 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
$input = shift;
|
|
||||||
$tmp1 = "/tmp/my-tmp.1.$$";
|
|
||||||
$tmp2 = "/tmp/my-tmp.2.$$";
|
|
||||||
$l1 = 0;
|
|
||||||
$l2 = 0;
|
|
||||||
$l3 = 0;
|
|
||||||
|
|
||||||
open(I, $input);
|
|
||||||
open(T1, "> $tmp1");
|
|
||||||
open(T2, "> $tmp2");
|
|
||||||
|
|
||||||
while (<I>) {
|
|
||||||
if (/^##*/) {
|
|
||||||
$line = $_;
|
|
||||||
chomp;
|
|
||||||
@a = split;
|
|
||||||
$count = length($a[0]) - 2;
|
|
||||||
if ($count >= 0) {
|
|
||||||
if ($count == 0) {
|
|
||||||
$l1++;
|
|
||||||
$l2 = 0;
|
|
||||||
$l3 = 0;
|
|
||||||
$label = "$l1"
|
|
||||||
}
|
|
||||||
if ($count == 1) {
|
|
||||||
$l2++;
|
|
||||||
$l3 = 0;
|
|
||||||
$label = "$l1.$l2"
|
|
||||||
}
|
|
||||||
if ($count == 2) {
|
|
||||||
$l3++;
|
|
||||||
$label = "$l1.$l2.$l3"
|
|
||||||
}
|
|
||||||
$indent = " " x ($count * 4);
|
|
||||||
s/^#*\s*[0-9. ]*//;
|
|
||||||
$anchor = "n$label";
|
|
||||||
printf T1 "%s+ [%s. %s](#%s)\n", $indent, $label, $_, $anchor;
|
|
||||||
printf T2 "<a name=\"%s\">\n", $anchor;
|
|
||||||
$line =~ s/(#+)\s*[0-9. ]*/$1 $label. /;
|
|
||||||
print T2 $line;
|
|
||||||
} else {
|
|
||||||
print T2 $_, "\n";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next if /^<a name="n[0-9.]+">/;
|
|
||||||
print T2 $_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(I);
|
|
||||||
close(T1);
|
|
||||||
close(T2);
|
|
||||||
open(T2, $tmp2);
|
|
||||||
|
|
||||||
while (<T2>) {
|
|
||||||
if (/<!\-\- OUTLINE \-\->/) {
|
|
||||||
print;
|
|
||||||
print "\n";
|
|
||||||
open(T1, $tmp1);
|
|
||||||
while (<T1>) {
|
|
||||||
print;
|
|
||||||
}
|
|
||||||
close(T1);
|
|
||||||
while (<T2>) {
|
|
||||||
if (/<!\-\- ENDOUTLINE \-\->/) {
|
|
||||||
print "\n";
|
|
||||||
print;
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(T2);
|
|
||||||
|
|
||||||
unlink($tmp1);
|
|
||||||
unlink($tmp2);
|
|
||||||
exit(0);
|
|
|
@ -1 +0,0 @@
|
||||||
{host, "localhost", []}.
|
|
|
@ -1,4 +0,0 @@
|
||||||
{flu,f1,"localhost",20401,[]}.
|
|
||||||
{flu,f2,"localhost",20402,[]}.
|
|
||||||
{flu,f3,"localhost",20403,[]}.
|
|
||||||
{chain,c1,[f1,f2,f3],[]}.
|
|
|
@ -1,4 +0,0 @@
|
||||||
{flu,f4,"localhost",20404,[]}.
|
|
||||||
{flu,f5,"localhost",20405,[]}.
|
|
||||||
{flu,f6,"localhost",20406,[]}.
|
|
||||||
{chain,c2,[f4,f5,f6],[]}.
|
|
|
@ -1,7 +0,0 @@
|
||||||
{host, "machi1", []}.
|
|
||||||
{host, "machi2", []}.
|
|
||||||
{host, "machi3", []}.
|
|
||||||
{flu,f1,"machi1",20401,[]}.
|
|
||||||
{flu,f2,"machi2",20402,[]}.
|
|
||||||
{flu,f3,"machi3",20403,[]}.
|
|
||||||
{chain,c1,[f1,f2,f3],[]}.
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue