Compare commits

...

3219 commits

Author SHA1 Message Date
LJ Sinclair
6222e9eb58
Update README.md
changed links to the community help repo
2024-02-22 10:20:41 +11:00
Коrd Campbell
c31eb2b64e
Update README.md with community 2023-05-30 10:26:47 -05:00
Коrd Campbell
c59a714d37
Create OPENSOURCE.md 2023-05-30 10:24:36 -05:00
Seebs
6383a96ac5 treat Percentile as an error if we can't use PQL Percentile
If we can't successfully generate a PQL Percentile call, error
out rather than implementing an actual Percentile function in SQL.
This can be revisited if anyone needs it.
2023-04-07 15:52:26 -05:00
Seebs
c658e771b0 make percentile work on Decimals, also make Percentile slightly better
So there's a lot going on here.

Percentile just did not work, even a little, with decimals.

In theory we try to make the int val part of ValCount work, in
ValCountize, but you can't actually use that for everything because
it unconditionally adds bsig.Base even when it shouldn't. But it
doesn't matter that we were returning those values from, say,
(Field).MinForShard, because ValCount.Smaller was not preserving them
when identifying the smaller of two Decimal ValCounts anyway.
And even if it did, the logic in Percentile wouldn't have worked
with passing the raw unscaled integer in as a value to compare
against.

But that's fine because the logic was also more generally wrong.
According to the existing logic, a value is the median value if
exactly as many values are less than it as are greater than it.

This is... not actually very accurate to what we usually mean by
"median". Because some values are *equal* to a given value. So
for instance, say you have the values {1, 1, 1, [a million 2s], 3}.
Our logic would regard 2 as being too high to be the median, because
3 times as many values are lower as are higher.

New interpretation: Imagine a sorted list of all your values, with
N entries. You want the Nth percentile, which is to say, you want N%
of values to be less than the vale you pick, and (100-N)% to be greater.
You can round both of these down. So for instance, if you have 6 values,
and want the median, you want 3 values greater, and 3 values less. To
be picky, we could demand the average of those middle two values, but
we're not in a good position to do that in this implementation.

If the number of desired things less than, or greater than, a target
is 0, we can short-circuit to the minimum or maximum value. This can
happen when nth is close to an end and the number of things is small,
not just at nth=0/nth=100.

So we rework this, and we rework the tests for this behavior to reflect
that logic.

We change executePercentile to be able to return a nil rather than
a weird ValCount in cases where there's no result, such as when
there's no values to compute a percentile of.

We also change the SQL tests to match the new behavior, since some
of them were expecting everything done on a decimal field with values
10-13 to come back as 10.00 as a decimal because that is what the
code returned.

We also propagate these changes to DAX, and along the way, fix up a
TODO item in the DAX copy, and stop skipping the test that was
failing because of that TODO item.
2023-04-07 15:52:26 -05:00
Seebs
7cf2c5b07e handle integers as comparisons for decimal fields
It's reasonable to allow "where x > 13" on decimal
fields. Handle at least int64 and float64.

Once this is up, we find that aggregates can return
non-values, such as nil, in some cases; for instance,
`percentile(x) where x > 13` can yield a nil if x is
never greater than 13, rather than making up a value
from zero data points. So we accept nil as a valid
result type in PQL aggregates.

As a result of this, change two tests which were
unintentionally testing for an arcane edge case bug
in which (1) we can't render a condition to PQL,
such as because you specified an integer for a decimal
field, and (2) the filter is using an aliased name,
in which we would end up failing to generate a PQL
filter, but *also* losing the SQL-layer filter, and
produce wrong results as though there were no filter.

We also alter the tests to use `o.price > 9`, because
this lets us generate three user names, but only two
distinct user names, so the test using DISTINCT returns
a different value than the test not using DISTINCT,
which helps us verify that it's actually working and
not just lucky.

As part of fixing that, there was an intermediate
state where we rejected as an error any case where
generating the PQL filter failed. This broke 21 more
test cases, but in all of those cases, the SQL filter
was actually working.

... But in two of them, we SHOULD have been able to
generate PQL, because they were testing bools for
null, which works fine. We just had a list of
field types we allowed null tests against and
omitted bool because I forgot that bool isn't always
just treated as a kind of mutex.
2023-04-07 15:52:26 -05:00
Seebs
0412a505c9 Pass filters down to Percentile correctly
When pushing an expression down to PQL Percentile, if we have
a filter, it has to be passed as the argument "filter", not as
an additional child argument. We don't need to pass in `All()`
as a filter if there's no filter, Percentile works fine with
no filter provided.
2023-04-07 15:52:26 -05:00
Pat Okeeffe
2bdc30c4f0
fix regex generation (#2377) 2023-04-07 14:10:16 -05:00
David Kagan
24a45bc30d
Cloud 1475 (#2371)
* working on incorporating regex logic

* Implemented a validation check for database name with given rules in doc within controller

* fixing tests to pass

* reflecting changes to match docs

* fixed tests further, hopefully

* for sure fixed integration tests, and moved validation check

* integration tests passed, go test now will pass

* fixed name size to 230 due to previous commit acknowledgement

* fixed field test negative validations

* added missing comma
2023-04-07 15:08:07 -04:00
Pat Okeeffe
7f75193cf2
tidy up show tables behavior (#2374)
* tidy up show tables behavior

* made cli integration test whole again

* Update fbsql \d meta-command to show system tables (#2376)

---------

Co-authored-by: Travis Turner <travis@molecula.com>
2023-04-07 12:58:09 -05:00
Adrian Walker
3b142af2c7
CLOUD-1456: SERVERLESS - CREATE DATABASE (#2375)
statement without a units qualifier causes it to be set to 0

Co-authored-by: Adrian Walker <adrian.walker@molecula.comm>
2023-04-07 12:44:45 -05:00
Pat Okeeffe
c619b7d94e
implemented query hints (flatten) (fb-2124) (#2373)
* implemented query hints (flatten)

* improved testing
2023-04-06 17:28:24 -05:00
Seebs
c66d392c87 uncomment old LIMIT tests, make them pass
We forward-ported a handful of tests from the previous parser
which relied on LIMIT clauses, but then we didn't support that.
Now that we do, we uncomment most of these tests, and actually
give them the correct data structures to compare with.

We leave two tests commented out. One was using `limit 10, 5` to
express a limit plus offset, and the other is using `not fld = 1`
as a WHERE clause, but we don't support unary-not to negate
other expressions.

In the process, we discover that converting a SELECT with a
LIMIT clause back to a string has a missing space, and fix that.
2023-04-06 11:49:11 -05:00
Lory Cloutier
875999e30d
Add test coverage to expressionanalyzer.go (#2370)
analyzeExpression - tupleLiteralExpression was covered by something
else between the ticket getting filed and me starting on it.
(*ExecutionPlanner).analyzeBinaryExpression now has increased
coverage for IN / NOT IN. Several bugs got revealed by adding tests;
those tests are commented out but can be re-enabled by whoever ends
up working on the bugs. Tickets are filed.
2023-04-06 09:55:09 -05:00
Travis Turner
ea72396b4d
Remove Node from data model; standardize on Worker (#2366)
* Remove Node from data model; standardize on Worker

This commit does a lot of things, but in general it attempts to simplify
the data model by getting rid of the Node and NodeRole models. Instead,
these will use the Worker model, which itself has individual boolean
fields for role types.

Get rid of roleType in some FreeWorker methods

rename NodeService to WorkerRegistry

simplify the freeworker interface

fix the tests

* Remove DeleteWorker method from workerJobService
2023-04-04 20:20:53 -05:00
Pat Okeeffe
284f62dcb9
create model, create function... all the goodies (#2264)
* create function, create/drop model; re-introduced limit; added COPY; var(); corr()

* review feedback
2023-04-04 17:44:29 -05:00
Seebs
c8c88ab0ee don't panic on failed table creation
The attempt to set the TrackExistence option for fields
happened before checking whether the field was created
successfully or not. Credit to Rachith for spotting this.
Bug was introduced with the TrackExistence stuff, but
we apparently never had a test case for invalid min/max
values.
2023-04-03 16:29:21 -05:00
Seebs
2af417d5c2 don't panic on a MIN that isn't a call
parseOperand was assuming that any reference to MIN in a place
where an operand was expected was a call, which it should be,
but it might not be. parseCallExpression panics if it doesn't
find a parenthesis, because it's never supposed to be called
when we don't know we have one.

The test for this is in with MinMaxColumnConstraints, even though it's
actually a test of MinMaxFunctionCalls, because that's where the other
tests involving the special MIN/MAX tokens live.

We also stop checking whether MIN or MAX might actually be QIDENT.
If you use a quoted identifier, we're over in the QIDENT case,
not the MIN/MAX case. If the token was MIN or MAX, it's always
unquoted.
2023-04-03 16:29:21 -05:00
Lory Cloutier
7031f7b968
Fb 2048 (#2363)
* Add test coverage for executionplanner.go
*ExecutionPlanner.mapper does not get tested in the case where its
context gets cancelled. In order to make testing this possible,
I've added a context argument to sql_test.MustQueryRow. If it's
nil, MustQueryRow creates a context for itself just like it always
has, but if a context is provided, it uses that.

* Adds test coverage for ExecutionPlanner.mapper in executionplanner.go
The case where the context gets cancelled mid-query is now covered.
The test is timing-dependent - the cancel call has to happen after
the query has been started but before it finishes, and in just the
right part of MustRunQuery, in order to actually produce a context
cancelled error, and not, say, a query cancelled error. May have to
adjust timing if the current delays don't work in CI testing.

* Addressed review notes
-reordered arguments for MustRunQuery
-moved MustRunQuery out of a goroutine, put the cancel in one
2023-04-03 12:04:41 -05:00
David Kagan
9e67f1dddd
Cluster nodes for serverless (#2336)
* slowly making a serverless systemAPI for ClusterNodes()

* implemented some methods for fb_database_info

* fixed linting

* fixed comments
2023-04-03 11:13:08 -04:00
Vengata Krishnan
b5dfb07118
Improve test coverage for ast components in ast.go (#2355)
*Tests are added to extend coverage for statement, expression and source types and many of the ast helper functions
*For those SQL language elements where ast exists but parsing is not implemented, test coverage is added to test only the ast correctness
*Also, removed timestamp EPOCH related compiler code as they become unreachable after their ast equivalent were removed in a previous PR.
2023-03-31 14:27:18 -04:00
HHans09
52f9703585
fb-2030 - added test cases for Joins in sql3 (#2359)
* fb-2030 - added test cases for Joins in sql3

* test cases for joins

* Revert "test cases for joins"

This reverts commit 1501f7b202.
2023-03-31 11:52:19 -04:00
Travis Turner
8fca15e936
RetryWithTx (#2348)
* First pass at RetryWithTx

* Refactor RetryWithTx to take a writable bool (instead of reads, writes)

* Implment DirectiveMethodDiff

This commit adds support for a Directive to contain only the diffs (as
opposed to the full Directive).

* Update controller tests to allow for DirectiveMethodDiff (over Full)

* Update RetryWithTx to retry on duplicate key constraint.

If two concurrent processes call IngestShard() for the same shard, both
were trying to insert the same job into the jobs table. That resulted in
a duplicate key error from the database. We want to include that error
in the list of errors for which RetryWithTx should retry.

* Remove unused method: Directive.TranslatePartitions()

* Replace query in a loop with a single query

We had a query which was looking to see if a job already existed. That
query was inside a loop, and could potentially generate 256 queries (for
example). This commit replaces that logic so that we use a single query
wiht an `IN ()` clause.

* Convert to directive version-by-address

This commit uses a separate directive version per address. It moves the
version get/increment back inside the buildDirective method so that if
two concurrent processes are building a directive for the same address,
one of them will get rolled back trying to commit the version update.

* Migration for directive version by address

* Add a comment about DirectiveVersion lock/unlock logic

* Remove AddLastWins

* fix linter

* handle error in walkdir

* fix test failures from removing AddLastWins
2023-03-30 20:54:37 -05:00
Seebs
a5dda0cb1c off-by-v error in spelling of versions 2023-03-30 17:34:59 -05:00
Seebs
9460bc9ee4 handle tag-only commits with no hash in version
When doing the release process, we generate version numbers
that have a version tag but don't have a hash. The IDK test against
the expected hash doesn't work in this context. Let's check for an
expected tag first.
2023-03-30 17:00:22 -05:00
rachithrr
0201649848
Adding fbsql binary to featurebase tarball (#2358) 2023-03-30 14:04:22 -05:00
Matthew Jaffee
c8199d765e
update ECR-related Makefile targets to get account ID automatically (#2357)
account ID is based off the AWS_PROFILE currently set in the environment
2023-03-30 13:26:09 -05:00
Bruce Baranowski
ad3f2d8f2d
fb-2040 (#2354)
*InbuiltFunctionsset tests
2023-03-28 16:59:00 -04:00
Seebs
283b00c741 hacky workaround: use locking to quiet race detector problems
So we have a problem which is triggered in part by the race detector,
but which is actually deeper, but also possibly rare enough to be
politely ignored.

The real underlying issue is that sometimes when we have multiple
tests running in CI, multiple instances of the CLI test end up using
the same postgres database backing for some of their DAX stuff. We
have workarounds for this in some places, but not others.

But the *observed symptom* of this is that it can cause a trivial
race detector issue where we have one call to `(*Resource).Lock()`
and another call to `(*Resource).IsLocked()` which aren't synchronized
in any way, so if the race detector spots this, it complains.

We can suppress that very easily by synchronizing these. That does
not solve the other possibly-weird problems, so this may not actually
address the issue, but I think it might reduce the rate of sporadic
failures significantly, which would give us some time to think about
solving the deeper problem.

The underlying design issue is that we're reusing the database name
in postgres for testing. This lets us have bounded growth (one database)
while leaving the database contents up after a failed test (so we can
examine them), then truncating the database during startup if it already
exists. Which works fine if *only one thing runs at once*, which would
be true on a laptop, but in CI, it's sometimes not true. A real fix
for that is complex and requires some rethinking of how we approach
the test stuff, as we don't want unbounded growth, but we also don't
want two copies of the test running at once to see each other, and
ensuring cleanup after a test failure is surprisingly hard.
2023-03-28 11:56:23 -05:00
Lory Cloutier
ad5f1d4eaa
Add test coverage in compilebulkinsert.go (#2353)
Assignment compatibility checking in analyzeBulkInsertStatement is
now tested. This isn't checking the values themselves, it's there
to make sure the structure is correct for mapping values to columns.
2023-03-27 17:01:59 -05:00
Seebs
f4905891d4 unbreak nested joins
It turns out that the problem with nested joins was that we were
trying to cleverly invert them, but that seems to be incorrect and
resulted in incorrect nesting.

The test case for this is
	SELECT * FROM X INNER JOIN Y ON true INNER JOIN Z ON false
this is now parsed as
	(X inner join Y on true) inner join z on false

Which, as it turns out, is the structure that stringizes back to the
original statement.

We were previously parsing it as
	X inner join (y inner join z on false) on true
which stringizes out to a different form, and is also, I think,
just straightforwardly not what we want.

So basically, we had special case code to recognize that we
were doing a join on top of another join, and invert them in
some way, and I have no idea why because that seems not to be
correct, or at least, it produces nonsensical stringizing that
we can't then parse.
2023-03-27 16:56:29 -05:00
Seebs
3f7ae75e17 increase parser test coverage significantly
We now test the tuple-assignment at all, although it's
perhaps confusing because we expect a ()-list of columns
to go with a {}-list of values. We also test a lot more
errors and some more successes, and additional literal types
in mustParseLiteral.
2023-03-27 16:56:29 -05:00
Seebs
d4fb807664 drop unused isHex and IsInteger functions 2023-03-27 16:56:29 -05:00
Garrison Davis
eb0640f175 Force rebuilding idk pilosa images 2023-03-27 13:34:43 -05:00
Seebs
63368d5e03 export git SHA commit for IDK tests
This is a sanity-check after a weird CI failure; we want
to ensure that we're actually getting the expected version of
featurebase. The environment variable here is magic to the
IDK tests.
2023-03-27 13:34:43 -05:00
Seebs
ef078ac5a0 add IDK test for expected featurebase commit
We have had some weird problems that look like IDK was being tested
against the wrong version of featurebase. Add a test which requests
the version, and if an environment variable is set, requires that
the featurebase server agrees with it.
2023-03-27 13:34:43 -05:00
Lory Cloutier
d114680222
Add SQL3 test coverage for expressionagg.go (#2351)
FB-2045
aggregate{Avg,Min,Max}->Update now tested for DataTypeDecimal.
{avg,min,max}PlanExpression->WithChildren now tested.
percentilePlanExpression->{Evaluate,Plan,WithChildren} is not
tested because percentile gets sent directly to PQL rather than
getting planned and evaluated in SQL.
aggregateLast->everything is not tested because Last is not yet
completely implemented.
2023-03-27 12:00:47 -05:00
Seebs
f12587f414 handle null results gracefully in SetContains{Any,All}
SetContains returns null if either of the values it's given
is null. SetContainsAny and SetContainsAll should also do this.
2023-03-24 16:01:09 -05:00
Seebs
2b4d49e502 standardize existence-tracking logic a bit better
We distinguish between "TrackExistence option is set"
and "we are actually doing existence tracking", to avoid
mishaps like accidentally creating an "existence" view for
a BSI field or something like that. This logic was being
done probably-correctly in one place, and ignored or
handwaved in some, so this is an attempt to just make
it more consistent.
2023-03-24 16:01:09 -05:00
Seebs
a3a0de2b0a rework and consolidate view name cleanup
We had two different versions of this, and a comment referring to a third
which doesn't exist, so I've consolidated them and made them slightly
pickier, to avoid problems like the one I ran into developing the existence
tracking where one of these optimistically transformed names it actually
shouldn't have. Now if we don't expect a view name, we yield an error,
rather than silently performing a transformation.

This also implies updating the ImportRoaring_MultiView test to use
two valid view names.
2023-03-24 16:01:09 -05:00
Seebs
54dbeec1af support null/non-null tests for non-BSI fields
There's a lot going on here. First, we were treating "the test is
a Condition" as implying BSI, which it doesn't anymore. Second, the
behavior of conditions was weird and BSI-specific. Third, we had
to propagate these changes and features throughout a bunch of code,
including both the core featurebase code and the DAX replacements/copies
of it, plus the SQL3 layer.

We refactor this so that tests for equality and inequality work for
non-BSI fields, so now if you accidentally use `==` in a Row call
on a non-BSI field, it still works; that's not specific to BSI
fields anymore.

We add a TrackExistence flag to fields, and propagate it through
things like our protobuf code, etcetera, so that we can successfully
create fields. Newly-created fields get this by default, because
we add it unconditionally to them, but the paths that are being
called with existing fields don't add it. So, when we "create"
(really, just load the definition of) a field from something stored
in the schema, we don't add TrackExistence to it, but any path to
creating a new field should.

A time quantum field with NoStandardView will *effectively*
lack TrackExistence.

For sets, mutexes, and time quantums with a standard view, anything
that sets bits will also set a corresponding bit for the record in
a new "existence" view. This allows us to distinguish between an
empty set and a null, and also allows null checks to be constant-time.

When clearing bits, we don't clear existence bits EXCEPT that if
you clear a bit in a mutex, *and the bit actually existed*, we clear
the existence bit. For sets and time quantums, clearing bits never
clears the existence bit.

Deleting records clears the existence bit.

We also add code to the `batch` subpackage to generate suitable
existence field bitmaps and import them. This logic correctly handles
empty sets and nils. The `batch` package does not allow specification
of anything equivalent to clearing a single bit from an existing
record, so we don't have to deal with the mutex complexity in that
case, which is good because it would be impossible.

This requires a number of other subtle changes, such as allowing
new fields to have more than one FieldOption specified for them.

We also drop the handful of implementation bits relating to the
"fullySorted" internal-use-only import flag, which existed only to
support the JSON ingest API, which we've removed.

The most dangerous part of this is that the mutex semantics are
impossible to implement on top of our existing API, because they
require us to know, not how *many* bits we cleared, but which
*specific* bits we cleared. I've implemented this as a new Tx method,
which is almost certainly going to be tech debt one day; if we some
day drop the Import API, we should remove that.

The testing for this is only currently covering the Set/Clear
behavior of PQL, and the Import API. The batch tests haven't been
written yet.

Fields that don't have existence tracking enabled refuse to perform
null/not-null tests. They should also report themselves as having
no null values -- if a record exists, sets in it are considered
empty rather than null.

The SQL3 support requires a number of subtle modifications to both
featurebase and some addon tooling. The essential thing is dropping
the unconditional translation of nil slices to non-nil empty slices
in translateResult, both in the executor and the orchestrator. We
also modify the logic that handles generating results from Extract
calls, to ensure that non-null sets get an empty slice created for
them even if they never have any values assigned.

The expected results for some tests are different now; we expect to
get nil slices, rather than 0-length non-nil slices, for fields which
were never written for a given record. Most tests were not changed.
(In every case, if a test was failing, I actually checked the logic
before changing expected results. This required a lot of tracking down
of edge cases.)

The batch package now rejects as an error attempts to clear single
bits from mutex fields, because so far as I can tell it's simply
impossible to have a roaring import that specifies the correct semantics
there; you can't tell whether to clear an existence bit without
access to the currently-set bits, which the batch API doesn't have.
We already supported the special case of specifying a clear value
of nil for clearing a mutex field; now that is the only allowed
value for a mutex field to have in row.Clears.

We change the logic for fixing up incoming view names (in two places)
to stop assuming that any view in a time field other than "" that does
not have viewStandard as a prefix is a partial time quantum name that
should have "standard_" prepended to it. This allows us to submit
bitmaps for "existence" to time quantum fields and not have them
silently transformed into "standard_existence" because that's what we'd
do with "202203".

We drop the field ClearBits method, which was totally unused.

We drop the sliceDifference function, which was used in a previous
mutex implementation and hasn't been used in ages, and the test
case for it, and the helper function used only by that test case.
2023-03-24 16:01:09 -05:00
Seebs
0dfaddf7b4 fix old typo
At some point in some other refactor, this option got removed from the
function call it was supposed to be an option to.

But actually that was... not correct either.

Because if you look closely, it turns out that this test was completely
broken; we were ignoring the results that were in the test, and using
inline results, but that's okay, because we were also doing the wrong
query for the second test, and ignoring the Field Options specified in
the test... all fixed now.
2023-03-24 16:01:09 -05:00
tgruben
bc07fb4a96
SQL3 Test Coverage: complete coerceValue coverage (#2343)
* complete coereceVal test coverage

* sql between test

* optimized between operator

* basic operator test
2023-03-24 13:33:05 -05:00
David Kagan
dd90838deb
Cloud 1457 (#2347)
* added dupe check

* added dupe check for databases

* prevent dupe table names

* refactored table dupe search

* further refactoring

This commit, further refactoring of checking for duplicates are done with SQL commands
Also adjusted tests to confirm changes

* fixed linting errors

* moved the errors around to keep them consolidated in the dax package

also removed useless comment
2023-03-23 16:20:45 -04:00
Lory Cloutier
fc74c8ecde
Add tests cases for coverage in expressiontypes.go (#2345)
FB-2041
Added tests for typeIsTimeQuantum and typeIsSet and made them pass.
Added tests for DataTypeTuple cases in typesAreAssignmentCompatible.
Timestamp conversion checking is handled before it gets to that
point but I left those branches in as a backstop.
Checking to see if DataType[String,ID]SetQuantum can be assigned
to themselves doesn't appear to be reachable currently but left
those branches in, because something may use them in future.
Added one test to the DAX skip list since it's the IDSetQ version
of a StringSetQ test that was already on there, changed skip list
to refer to both tests by name instead of by number.
2023-03-23 14:17:06 -05:00
Vengata Krishnan
9e39eee9c9
fb-2049 improve test coverage for select statement (#2339) 2023-03-23 11:10:57 -04:00
Travis Turner
82700264e2
fbsql: add the --csv and --pset flags (#2342)
* fbsql: add the `--csv` flag for CSV output in non-interactive mode

* fbsql: add support for the `--pset=VAR[=ARG]` flag
2023-03-22 08:57:28 -05:00
Matthew Jaffee
8fe73146c8
Sqldb rip boltdb (#2341)
* serverless sqldb use same env for test config as normal

* rip boltdb implementation of controller backend out

it was replaced by postgres and no longer works properly.

This involved migrating a number of tests which only worked with
boltdb, which exposed several ways in which the postgres
implementation had slightly different behavior from the bolt
one:
1. ordering of results in some cases, and
2. (more importantly) erroring when a record to delete was not
found. The bolt implementation silently ignored it when things to
delete weren't found, so we make some changes to match that behavior.

Also stopped propagating CreatedAt and UpdatedAt from DB tables into
dax types. These were breaking existing tests. Perhaps it would be
better to actually use them, but for now they will only exist at the
DB level.

This change set also moves the insertion of the directive_versions
record out of migrations and into the startup/connection code. Having
this in the migrations was a bit ugly because you couldn't just
truncate all the tables and have everything work from
scratch. Inserting it during startup is fairly innocuous, and will
just continue on if it already exists.

* update directive_version test

I changed the initial value to 0 so that the first version that gets
sent out is 1
2023-03-22 08:54:13 -05:00
Travis Turner
f5f7c5e551
fbsql: add support for \d meta-command. (#2340)
`\d` will list tables (in the future it will also include things like
views)
`\d tablename` will show info about tablename
2023-03-21 21:10:31 -05:00
Travis Turner
10aab583c9
fbsql disconnect from database with \c - (#2338)
* fbsql disconnect from database with `\c -`

This adds the ability to disconnect from the current database by passing
a hyphen to the `\c` meta-command.

* Update cli/cli.go

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>

---------

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2023-03-21 19:21:40 -05:00
Travis Turner
2f7ae30784
Add HasDirective to dax.Node struct to force Directive on restart (#2335)
For on-prem serverless, if we restart the process containing the
controller and computer(s), when they come back up, the controller
doesn't know that the computers have been restarted, so it doesn't send
them a directive. This change forces the controller to send a directive
upon startup by a computer.
2023-03-21 13:22:16 -05:00
Vengata Krishnan
2cf972b5d1
fb-2036 improve coverage for create view statement (#2333) 2023-03-21 14:06:38 -04:00
seebs
0e70d80030
stop suppressing IDK tests, fix IDK test for DAX (#2334)
DAX now relies on Postgres, so we use the Postgres which is already in
the IDK tests (for the external lookups thing) to use as the
controller's metadata store as well. The env variables are a little
confused, but I'll clean that up separately.
2023-03-21 10:28:42 -05:00
Bruce Baranowski
ca99d47249
Add SQL3 tests - /planner/inbuiltfunctionsstring.go (#2331)
* scalar string function test expansion
2023-03-20 17:04:27 -04:00
Seebs
117cbd6590 retry thing that depends on something asynchronous
There's no actual way to forcibly sequence our check of the history
until after the history has been updated, but it's pretty fast usually,
just not always instantaneous. Without this, adding a few millisecond
delay in the tracker reliably produces the test failures we kept seeing
with an unexpectedly low length of 3. With this, it passes consistently
even with the artificial delay.

The query tracker being asynchronous is probably fine, but we need
to test it as though it might take a while.
2023-03-20 12:41:37 -05:00
Vengata Krishnan
693ea1c3a0
fb-2056 improve test coverage for alter table statement. (#2332) 2023-03-20 13:02:37 -04:00
Vengata Krishnan
72871e6e5d
FB-2054 - improve create table timestamp column type coverage (#2330) 2023-03-20 13:01:23 -04:00
Matthew Jaffee
be4f365eaf
Cloud 1358 bolt postgres (#2286)
Switch Serverless from using BoltDB to Postgres as metadata store.

Previously, the controller stored all metadata to BoltDB. This implements SQLDB (currently Postgres flavored) as the backing store for metadata. This will allow us to have multiple instances of the controller running for HA, and to easily inspect and repair the contents of the metadata store.

Unfortunately, it was not straightforward to keep the BoltDB implementation working alongside the SQL one, so it will be removed in a later patch. Once that's done, the SQL implementation should allow for a number of simplifications of the schemar and balancer interfaces.

Database migration is built directly into the application by embedding the migration files and logic from the `soda` command line tool. When connecting to the RDBMS, the app will always attempt to create the necessary database and apply any outstanding migrations.

Integration tests truncate all tables upon start, but *not* at the end, so the state of the database can be inspected after integration tests.

Had to refactor some of the controller's background tasks to make sure they get properly shut down on controller exit.
2023-03-20 09:02:22 -05:00
Vengata Krishnan
2c3be9d1e8
Fix failing selects on views defined with date literals (#2313)
* Fix failing selects on views defined with date literals
* System variables implementation.
2023-03-17 12:24:00 -04:00
Garrison Davis
9c082c5c77 Increase golangci-lint timeout to 8 minutes
This is the time being used in our other CI pipeline.

The alternative to doing this is ripping out all of this code so that
we're not running two CI pipelines...
2023-03-17 09:59:09 -06:00
Lory Cloutier
b729348c02
Add SQL3 test for oppqlgroupby.go (#2326)
FB-2027
The DataTypeIDSet and default branches in groupByColumns weren't getting tested.
Added tests to make sure they are now covered.
2023-03-16 14:58:19 -05:00
tgruben
7ae2f0225b
add test coverage for ordring by string, bools, and timestamps (#2327) 2023-03-16 14:51:57 -05:00
tgruben
c9c63b22b4
Add SQL3 Tests added bulk insert tests (#2324)
* added bulk insert tests

* test idset,stringset,bool in parquet

* bulk insert time coverage
2023-03-16 13:02:39 -05:00
Jacob Brinlee
ada48be181
check for valid name in kafka-config (#2321) 2023-03-16 09:16:31 -05:00
David Kagan
c10762220a
renamed 2 system tables (#2310)
* renamed 2 system tables

* adding table column for types

* added a type field to fb_database_nodes system table

* updated ClusterNode struct

* adding backwards compatibility

this commit also adds support for ordering systemTables and implements the method

* fixed linting

---------

Co-authored-by: Travis Turner <travis@molecula.com>
2023-03-15 17:43:11 -05:00
tgruben
f514474014
Test Row Append (#2323) 2023-03-15 13:13:44 -05:00
tgruben
e02ea2c2e7
SQL3 tests newMessageError and all the constructors (#2320)
* sql3 wire protocol message constructor tests

* convert to testify assertion, clarify comment
2023-03-15 12:41:35 -05:00
Travis Turner
aa17b8d725
Enable linter: stylecheck (#2317)
* Enable linter: stylecheck

This enabled the stylecheck linter, but excludes some staticchecks for
now. The following are ignored because they will take a bit of time to
address, but the intention is to address them and remove them from the
exclusion list.

ST1000: at least one file in a package should have a package comment
ST1003: golang naming standards
ST1008: error should be returned as the last argument
ST1016: methods on the same type should have the same receiver name
ST1020: comment on exported function

* Address ST1015

For some reason this failed in CI but not locally. I can't figure out
why that check isn't happening locally. This just moves the switch
statements around so that the `default` is the first (or last) item.

* Adjust error string in test to match case-adjusted error

* Remove TestCloseTimeout
2023-03-14 08:45:18 -05:00
Travis Turner
a8c2ff603d
Add CSV support to fbsql (#2318)
* Pre csv cleanup

* Implement the CSV writer

This adds the `format` sub-command to `\pset` in order to choose between
formats `aligned` and `csv`.
2023-03-13 17:41:08 -05:00
Travis Turner
37ee6ea482
fbsql integration test framework (#2308)
* stub out a test framework for fbsql

* Introduce fbsql integration test framework.

This also adds support for `pset location` to set the geo location (i.e.
time zone) in which timestamps should be displayed. And it adds support
for comments (lines starting with `--`) in the line reader/splitter.

* Replace Stdin and Stderr with setters and un-export them
2023-03-13 16:29:18 -05:00
Jacob Brinlee
cd32cd7696
handle empty avg agg (#2316)
* handle empty avg agg
2023-03-13 12:59:38 -05:00
Travis Turner
c79cc3b7db
linter: prealloc (#2315) 2023-03-11 21:19:05 -06:00
Travis Turner
d2856bfeee
Linters! (#2314)
* Add (commented out) linters that we should introduce

I went through the available linters and added (commented out) the ones
I think we should work on in the near term. In other words, fix them,
then uncomment them so they are enabled in CI.

* linter: errchkjson

* linter: ineffassign

* linter: gosimple

* linter: errname
2023-03-10 15:13:15 -06:00
Lory Cloutier
6de130fe39
Added date_trunc time/date scalar function (#2312)
FB-1961
Added function and test coverage.
2023-03-10 14:49:47 -06:00
rachithrr
ef14f3a560
FB-1894: Implement DateTimeDiff() (#2307) 2023-03-10 10:12:27 -06:00
Lory Cloutier
b17582110f
Change datepart function to datetimepart (#2303)
FB-1897
The specs for the datetimepart function are, as far as i can tell,
identical to the existing datepart function. Per Pat, replaced the
datepart function with datetimepart rather than just adding
datetimepart as an alias. Made sure existing tests that were using
datepart got switched over.
Second go at this after sorting out weirdness with git.
2023-03-09 13:04:38 -06:00
Jacob Brinlee
1f829f26b3
FB-1905: Test Consumer Close Timeout (#2229)
add config and closetimeout testing to Kafka consumer
2023-03-08 21:49:24 -06:00
Vengata Krishnan
4d484641f2
Gracefully handle divide by zero (#2306)
Divide by zero in SQL expressions will be reported as SQL errors.
2023-03-08 16:51:28 -05:00
Andrea Cappelletti
ecda941aac
Add platform specification when building binaries (#2302)
* Add platform specification

* Add new rule with platform specification

* Reformat code

* Refactor indentation and typo
2023-03-08 11:48:06 -06:00
rachithrr
909c62d44e
FB-1895: Implement DateTimeFromParts (#2296) 2023-03-07 16:47:07 -06:00
tgruben
dc6cbad3fc
compileOrderingTermExpr needs to return alias and not expression (#2300) 2023-03-07 15:56:58 -06:00
Travis Turner
29a5ac971f
Add default fbsql cloud configuration (#2301)
Until we have API token support, connecting to cloud requires the
cognito configuration. This commit adds the production cognito settings
for defaults, and we have intentinally omitted these from the documentation.
2023-03-07 14:52:12 -06:00
Lory Cloutier
7ea4135ecf
Add datetimename function to SQL3 (#2293)
FB-1896
Added the datetimename function, which returns parts of a timestamp
as strings. Month and day of the week are named ("January", "Monday")
while others are returned as a string of digits ("2023").
Added tests to the test definitions.
2023-03-07 12:58:44 -06:00
Travis Turner
05ebdd15f0
Minor cleanup to some fbsql flags and meta-commands (#2299)
* Set fbsql prompt based on the connected database

This also changes the prompt to align with psql, where it begins with:
db=#
and the mid looks like:
db-#

* Require organizationID in on-prem, serverless queries

* Support meta-commands in `--file` command

I'm not sure why this was restricted before. Just an oversight.

* Change default history file name to fbsql_history

* Add port short flag: p

* Support meta command \list (for \l) and \out (for \o)

* cleanup while writing docs

* Have \cd with no arguments change to home directory

* Avoid shadowing `action`
2023-03-07 12:18:55 -06:00
Vengata Krishnan
0708673df5
fb-1893 Adding new scalar SQL function datetimeAdd(timeunit, duration, target) (#2295)
* fb-1893 Adding new scalar SQL function datetimeAdd(timeunit, duration, target)
2023-03-07 11:16:00 -05:00
Travis Turner
eb6c6e3105
Add kafka support to CLI (fbsql) (#2278)
* Add kafka support to CLI (fbsql)

This commit adds the ability to provide a `--kafka-config` command line
argument referncing a toml file to configure kafka.

* Move "Molecula Consumer" message to the logger; hide it in basic mode

* Fold decimal(scale) into kafka.source-type

* Build fbsql with cgo in docker for CI

* Re-organize the fbsql kafka config and setup.

Allow field config to use the table schema if no fields provided.

* Display timestamp fields with format RFC3339Nano

* remove kafkaRunner (no longer used)

* Fix cli/batch test (and make sure it's not excluded from CI)

The logic in our Makefile was exluding from tests any package with
`/batch` in the package name. This excluded `/cli/batch`, which is not
good.

This commit changes the exclusion logic to include the `/v3` portion of
the package name, so `/v3/batch`.

* Rename Basic() to SetBasic()
2023-03-07 08:18:22 -06:00
Seebs
244d80753e reuse clients instead of making new clients
Buckle in, this one's a ride.

This is attached to the same PR as a fix for exiting abruptly
during some tests because I ran into that issue, and comprehended
it, while trying to track down weird and sporadic test failures
that were actually this issue.

The actual, underlying, problem: `make test`, by running all the
tests at once, was hitting a bug that was mostly effectively
triggered by running the `dax/test/dax` tests, and the top-level
`featurebase/v3` tests, at the same time. However, the interaction
was nothing as obvious as temporary files, etcd configuration,
or whatever.

We were running out of port numbers.

The tests were using a bit over 30k simultaneous established TCP
connections, each to different ports, because we were creating
new clients for basically every single operation. For instance,
in a single SQL test that did an import and then a read, we
were creating a new client for each field written to, and then
also creating a new client for each field in results that needed
key translation. And none of these clients were closed or
timed out in any way. In fact, Go doesn't really *do* "closing"
of clients; the closest is that an http.Client can be told to
close idle connections that it has been keeping open.

The worst offenders were both named `fbClient`, and were nigh-identical,
except one of them was implemented as a method on `importer` in the
IDK tree, and one was a standalone function.

It may seem surprising that the method on `importer` is using a shared
client pool for all importers, rather than a new pool for each
importer. This is because we potentially make quite a few importers
during tests.

Before this, running either of the dax tests or the top-level
tests would show well over ten thousand simultaneous ESTABLISHED
connections. After this, the dax tests used nearly twenty.

The problem with port consumption like this, while more noticeable
on MacOS, is also something we could hit on the CI runners, especially
if a single runner ended up with more than one test suite running
at the same time. This probably manifests as sporadic very strange
failures of CI, with messages about "cannot assign requested address".
(Note that an outgoing connection to a successfully-created port
requires *another* port to be assigned for the outbound socket.)

This was complicated dramatically by the fact that, for some
utterly cursed reason, it was *especially* common for the point
at which we hit this, in the top-level featurebase tests, to be
running one of the backup tests in TestVariousQueries, and
specifically, to be hitting it on the dataframe part of the
backup... Which is to say, on the *one* path in the backup function
that called log.Fatal, and thus terminated the featurebase process
abruptly without further commentary.
2023-03-06 13:12:22 -06:00
Seebs
f3abd11884 don't use things that instantly exit in a code path tests hit
The testing package is full of subtle magic, and one of the most
subtle is this: t.Logf, etcetera, all write to a buffer which is
then displayed after the test is run. Which means that, if you
exit, the buffer is never displayed. This means that, if a test
case can fail in a way that causes an instant exit, you don't
hit defers, you don't get your log messages, you just get a mysterious
exit of the process.

We have two cases where backup commands were calling log.Fatal
instead of returning an error. The error in question is displayed
correctly and informatively if returned, so we return it.

We also have one case where we were using os.Exit to avoid a
deadlock. Instead, we make the thing that would deadlock
conditional on the test not having failed. In the event that
the test fails, we now print our failure message correctly,
then also report an unclosed cluster. That's fine.
2023-03-06 13:12:22 -06:00
jacob
549566b6c2 kafka delete functionality 2023-03-06 09:52:31 -06:00
jacob
33d05e6267 limit parallel testing 2023-03-06 09:52:31 -06:00
jacob
e9796e1aed adding kafka delete functionality 2023-03-06 09:52:31 -06:00
jacob
aad32f1dbd adding kafka delete functionality 2023-03-06 09:52:31 -06:00
dependabot[bot]
c4b0e1e1fb
Bump minimist from 1.2.5 to 1.2.8 in /lattice (#2289)
Bumps [minimist](https://github.com/minimistjs/minimist) from 1.2.5 to 1.2.8.
- [Release notes](https://github.com/minimistjs/minimist/releases)
- [Changelog](https://github.com/minimistjs/minimist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/minimistjs/minimist/compare/v1.2.5...v1.2.8)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-03 16:09:14 -06:00
tgruben
dba15669c6
fb-1915 Support large id's in NDJSON (#2290)
* uses json.Decoder to allow for large integer values in ndjson format in bulk import
2023-03-03 15:37:56 -06:00
Garrison Davis
7b8b3d8e4f Remove pre_clone_script 2023-03-02 17:24:43 -07:00
tgruben
cbbaba98cd
Use json.Number decoder to handle large ints in sql wire protocol (#2285)
* Use json.Number decoder to handle large ints in sql wireprotocol
2023-03-02 14:49:55 -06:00
dependabot[bot]
4c0bb3b7c1 Bump golang.org/x/net from 0.2.0 to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.2.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.2.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-02 13:21:48 -06:00
Garrison Davis
5c22c9803a Add default retries 2023-03-02 11:55:02 -07:00
Garrison Davis
ffdb308472 Remove manual git clean from CI 2023-03-02 11:55:02 -07:00
Garrison Davis
f0e1b72834 Add CI_PRE_CLONE_SCRIPT to .gitlab-ci.yml 2023-03-02 11:55:02 -07:00
Pat Okeeffe
9386fc75b2
implement select from time quantum columns (fb-1654) (#2282)
* first time quantum queries working

* implement select from timequantum columns

* skip a dax test

* make linter happy

* addressed review feedback

* reverted over eager test elimination
2023-03-02 00:06:58 -06:00
seebs
b35c240da7
handle count(*) in having correctly (#2274)
* correct reference for `having count(*)`

It turns out that `having count(*) ...` was always treating
the count(*) as exactly 1. After studying this a lot, I noticed
that in fact, we correctly handle other counts. The reason is
that there's already code to recognize aggregates in `having`
clauses as matching aggregates that are being computed -- but
it only covers the other aggregate clause types, not the newly
added `countStarPlanExpression` from making `count(*)` work even
if there's no `_id` field.

We add several corresponding test cases.

* fix sum(a_decimal) type conversion

Added a test case for this, and also added a fix for it.
Underlying issue: qualifiedRefPlanExpression could end up
producing an int64 instead of a pql.Decimal, even though it
had expected type Decimal.

Originally this worked by politely converting an int64 to
a pql.Decimal in the Evaluate phase, but this was not ideal;
the real question is why it was coming out as an int64 at
that step. Showed this to Pat, who spent a while studying it
and produced a better fix.

* temporarily comment out test which fails in DAX
2023-03-01 23:49:45 -06:00
Fletcher Haynes
a479441ea2 Reverted some testing log messages and commented out code 2023-03-01 21:43:53 -08:00
Fletcher Haynes
21bc76ddb2 Removed cobra option to ignore parse errors of flags since we are using MarkDeprecated 2023-03-01 21:43:53 -08:00
pokeeffe-molecula
11e6d2d9a5 this now prints a message 2023-03-01 21:43:53 -08:00
Fletcher Haynes
660428d5fb This changes the server sub-command to ignore unknown flag. Fixes FB-2019 2023-03-01 21:43:53 -08:00
Vengata Krishnan
6a3c47dbe1
fb-2013 removing sql feature flag entirely. (#2283)
Make SQL endpoint always available.
2023-03-01 15:12:04 -05:00
seebs
b7e9879526
forward-port tests from SQL1 tree (#2261)
This forward-ports a number of tests from the previous SQL
implementation. The porting is approximate in a number of ways,
and not all tests are implemented/tested yet.

In particular, several tests are currently disabled because
we don't support `limit n` constructs.

The tests that were primarily tests of the parser have been
brought forward as parser tests. One of them has been altered
to add parentheses, because our parser interprets
	fld1 between 1 and 3 and fld2 = 2
as:
	fld1 between (1 and 3) and (fld2 = 2)
which is invalid, while the old parser apparently interpreted it
as:
	(fld1 between 1 and 3) and (fld2 = 2)

We have not yet verified the SQL spec's requirements here, but
sqlite agrees with our old parser, not our new parser, so this
may be a regression.

The old tests expected an INNER JOIN to suppress duplicate
values. Our new code does not, which is consistent with other
SQL implementations. This is a change, but the old behavior
appears to have been wrong. (You can still suppress duplicate
values by specifying DISTINCT.)

In the previous implementations, a value like `count(*)` had
`count(*)` as its column name. In the new implementation,
it has an empty string as its column name.

Related to this, the prior implementation allowed you to
write
	select age, count(*) from grouper group by age having count > 1
but the new implementationt requires that to be spelled as
	having count(*) > 1

This is consistent with other SQL implementations, so I think
the new behavior is correct.

The behavior of SHOW COLUMNS and SHOW TABLES has changed, in
that the specific results returned are significantly different.
Perhaps more significantly, the old system spelled the former
query as SHOW FIELDS, rather than SHOW COLUMNS. This may be
considered a regression, in that `SHOW FIELDS` no longer works,
and we should consider whether any hypothetical users might
have been relying on the output of either of these. (I hope
not, the new output is much better.)

Some of the old tests (the ones in handler_test) were accommodated
by adding a couple of specific test cases to existing tests,
specifically:
	* handling timestamp values with `Z` rather than `+00:00`
	* a join with a WHERE clause referring to fields in both
	  source tables

We introduce a new "partial" comparison type, because there's
no way for a test of `SHOW TABLES` to contain a correct table
row, because `SHOW TABLES` includes timestamps from when tables
were created. I'm not sure this is the right way to do this.

We add corresponding changes to dax_test, because the DAX tree
tests against the SQL tests.

We change the returned types of field names and field types to
plain strings, ironically because DAX needs this -- the test code
in the DAX tree is getting them back as plain strings, rather
than as dax.FieldName and dax.BaseType.

The tests using `having` are commented out because they don't
seem to be working, a ticket has been filed for this.

Two of the tests that should return strings are instead returning
untranslated integer IDs, but only for DAX, not for the regular
SQL tests, and the `delete` test has been commented out for
DAX-specific errors. If we merge this, the next step is to
ticket those and address them separately.
2023-03-01 13:40:50 -06:00
Julio Martinez
b8e5e1f32c
Use curl instead of find so errors propagate. (#2227)
Co-authored-by: Julio Martinez <julio.martinez@featurebase.com>
2023-03-01 11:33:44 -08:00
Jacob Brinlee
ebb3c8a290
SUP-297 (#2265)
* log net/http with TLS and verbose only
2023-03-01 12:58:14 -06:00
David Kagan
f8e21b2798
SQL tests now that CodedErrors are across HTTP (#2284)
* 3 todos in delete_database

* forgot to remove some test options
2023-03-01 13:51:14 -05:00
Seebs
70f92bc038 actually yield checksums to caller
While fixing a bug that log messages were ending up
in the output buffer for backups, we fixed up a bunch of
things to do with log messages and output for various
commands.

Due to a subtle oversight, this means that since we did
that, executor_test's `chkSumCluster` has been dutifully
printing `hash:blahblahblah` to os.Stdout, and returning
an empty string.

This also, indirectly, fixes a very strange behavior
we've had ever since then, which is that a lot of test
output silently disappears. The reason is probably,
although I haven't found the right code path, that we
were ending up closing os.Stdout.
2023-03-01 12:48:00 -06:00
Seebs
841ef32545 force count to 1 to disable test caching
The caching of test results means that we get instant cached results
rather than actually running tests in some cases, which is virtually
guaranteed not to be what we want. There's almost no cases where
this actually speeds a thing up validly, and a lot where it speeds a
thing up invalidly.
2023-03-01 12:48:00 -06:00
David Kagan
d7c6258f16
Cloud 1359 errors across http (#2279)
* WIP: json marshal coded errors for http

* WIP: trying to see how best to implement the http-error tests

* finish stubbing out the Schemar methods in the test

* using json to move CodedErrors across boundaries and associated tests

* implemented feedback and fixes

---------

Co-authored-by: Travis Turner <travis@molecula.com>
2023-02-27 16:34:51 -05:00
Matthew Jaffee
933767ec07
move closing of profiling stuff to Close method so it runs for duration of process (#2277) 2023-02-27 10:41:53 -06:00
Vengata Krishnan
6777e3dc07
FB-1968 timestamp data type related fixes and enhancements (#2256)
* Removed support for EPOCH column constraint from TIMESTAMP SQL data type.
* Implicit conversion of integers to timestamp will treat the integer value as seconds since unix epoch.
* Add new ToTimeStamp(num, timeunit) SQL scalar function to help convert integer values to timestamp.
2023-02-24 14:57:17 -05:00
tgruben
dbea305638
add a batch size to limit upload payloads (#2275) 2023-02-24 12:30:57 -06:00
Garrison Davis
186da6b302 Refactor build-fbsql and upload to S3 in CI 2023-02-24 10:48:48 -07:00
tgruben
c294bc70dc
limit memory for backuptar/restoretar (#2270) 2023-02-23 18:35:52 -06:00
Travis Turner
528ebc93db
CLI variables (#2263)
* Add meta-commands \set and \unset (for variables)

* WIP: first pass at variable replacement

* Use a mapReplacer instead of having Command implement replacer

* remove circular reference with variables

* remove the `replacer` interface; just have it be a struct

* use a lexer for variable replacement
2023-02-22 15:52:58 -06:00
Travis Turner
a633b72f3d
Separate the featurebase and fbsql make build targets (#2272)
* Separate the featurebase and fbsql make build targets

Using the same build target was problematic because they shared the same
flags. Since the `-o` output flag was used, the fbsql binary was
overwriting the featurebase binary.

* make sure the make package target builds fbsql
2023-02-22 15:33:11 -06:00
Seebs
d1dbcabb3d fix cleanup logic for ramdisk usage
we want to be sure we delete the files we created during the
run even if the test run panics, but not files other runs
may have created also in /mnt/ramdisk.
2023-02-22 14:45:56 -06:00
Seebs
8724eb09b0 improve ramdisk config in Makefile, use it for everything in tests
So, we were special-casing creating a ramdisk, and setting a special
environment variable for it, for boltdb translate files, to improve
performance.

But actually, etcd and test cluster data and so on all go in $TMPDIR,
and if you move all of those also into a ram disk, you get way better
performance. But 2GB may not be enough for that.

So!

We unify on $TMPDIR, we bump the default size to 4GB, we make the
size configurable, and we stop using the name RAMDISK. This should
improve performance on MacOS significantly for `make test` and
things like it, and also simplifies our lives by not having a special
case for the boltdb translate files.

Also change the environment variable names used in our CI config.
(I don't see where we mount the ramdisks, but I think that's happening
in our setup.)
2023-02-22 13:19:06 -06:00
Jacob Brinlee
df7e813f01
SUP-302 (#2243)
* add ability to use Θ in all field names & with PQL
2023-02-22 11:30:14 -06:00
jacob
26747362e1 clean up time quantum test 2023-02-22 11:18:06 -06:00
jacob
67d247a479 adding time quantum testing 2023-02-22 11:18:06 -06:00
jacob
3b2111b31c adding some test data 2023-02-22 11:18:06 -06:00
jacob
864c6ad4e7 adding test avro to PDK for recordTime 2023-02-22 11:18:06 -06:00
jacob
bf37dfa9ba add name field to recordTime field 2023-02-22 11:18:06 -06:00
Julio Martinez
f65f7ffe95 Fix bad FLAGS env var passed when building to package. 2023-02-21 13:28:26 -06:00
Julio Martinez
7a839f2e8f
Build target also builds fbsql, fbsql is also packaged. (#2260)
Co-authored-by: Julio Martinez <julio.martinez@featurebase.com>
2023-02-21 08:55:27 -08:00
Lory Cloutier
d0e4012025
Fb 1975 (#2254)
* Store version-check file in the configured data-directory

This also fixes what I think is a bug.
It also un-exports everything.

I have questions.

* Version checking: clean up code, add server flags
FB-1975
Cleaned up version checking, removed a race condition, and added error checking.
Added server flags for check-in endpoint and UUID storage file.
Incorporates Travis's changes to store UUID file in data directory
and unexport most of verchk.go.

---------

Co-authored-by: Travis Turner <travis@molecula.com>
Co-authored-by: seebs <seebs@molecula.com>
2023-02-17 13:50:45 -06:00
Pat Okeeffe
e755fecf63
ORDER BY ....what now!? (fb-1954) (#2257)
* can now order by columns not in the select list

* added testing coverage
2023-02-17 13:35:36 -06:00
Pat Okeeffe
c749e07d03
add support for time quantum inserts with explicit timestamps (fb-1558) (#2262)
* added support for time quantum inserts with explicit timestamps

* fixed copy pasta
2023-02-17 12:06:46 -06:00
Seebs
66e079f1e9 task pool: avoid race condition on shutdown/close
When we close a task pool, we use a condition variable to wait for
workers to exit, if any workers are still running. The workers,
in turn, use the condition variable to notify that they've exited.
Unfortunately, the workers aren't using the lock (the rationale was
that it's all atomic ops so they don't need to), which means that
it's possible to have the following sequence:

	Close(): obtain current live count
	worker: decrement live count
	worker: send broadcast to condition variable
	Close(): wait on condition variable

To resolve this, we make the worker update also request the lock.

We add a simple reproducer for this. Note that simple doesn't mean
it fires completely reliably; on my laptop, the test causes a test
timeout about 60% of the time without the fix. If you add a short
delay between sampling the live count and waiting on the condition
variable, the deadlocks move from "60% chance of hitting it in
a million trials" to "nearly always".
2023-02-17 11:32:07 -06:00
Matthew Jaffee
41a6b9e823
controller commit to DB first then send directives (#2259) 2023-02-17 09:12:15 -06:00
Pat Okeeffe
74885c9718
make count(*) not depend on _id (#2258) 2023-02-17 08:46:25 -06:00
Travis Turner
393721c0ce
Add viper (for env variable) support to CLI (#2251)
* Add viper (for env variable) support to CLI

* Move the "featurebase cli" sub-command to its own "fbsql" command

I don't know if this is the final name, but putting it here as a
placeholder for now.

* Handle single `--command` flags.

This also adds a printer interface so we can opt NOT to print setup
information in non-interactive mode.

* Add support for multiple `--command` flags in the same call

* Add support for multiple `--file` flags

* Move members related to Config into a separate struct

* Make sure non-interactive mode can connect to a database

* comment fix

* support control-C on readline

* Prevent connection message from printing in non-interactive mode

* Return errors (instead of printing them) in non-interactive mode
2023-02-16 20:41:39 -06:00
tgruben
4172976e6a
Manual buffer management in restore-tar (#2249)
* manual buffer management
reuse buffer on backuptar as well
test coverage for backuptar
2023-02-16 14:57:00 -06:00
tgruben
6a9843b4a0
use primary as source for FieldTranslate backup data (#2255)
* use primary as source for FieldTranslate backup data
2023-02-16 12:13:11 -06:00
Pat Okeeffe
41b8505d70
Aggregation Nation (fb-1955, fb-1887) (#2252)
* make nodeid come from the correct table

* refactored aggregates; added ability to aggregate on expressions not just references

* addressed feedback

* now with the compiler errors fixed after rebase
2023-02-16 10:56:27 -06:00
Seebs
10b60f5d51 set default epoch for timestamps in system tables
If we don't set an epoch, we get a cryptic message on the console.
Note, this message isn't logged properly, it doesn't use the
logger, it uses the `log` package.

	2023/02/09 11:07:23 ERROR: converting timestamp options for
	end_time: checking overflow: custom epoch too far from
	Unix epoch: 0001-01-01 00:00:00 +0000 UTC

Because this uses the log package, it doesn't go to the same place
as other messages, making it a pain to debug.

The underlying problem is that a timestamp can't just have a zero
value for its epoch. So, we set a default epoch of 0 Unix Time.

We should possibly revisit the question of whether the conversion
in the top-level schema.go should handle an epoch which IsZero,
but I'm not sure what "base" should be in that case. In practice,
all existing usages except this one are specifying time.Unix(0, 0)
already.
2023-02-15 14:34:51 -06:00
Seebs
f4e1e63dd0 fix typo in file name 2023-02-15 14:34:51 -06:00
Seebs
5dffbccdff add test coverage, fix bugs caught by added test coverage
Note: We now skip a test because we can't pass it but fixing
it is presently beyond my understanding. In parser_test.go,
we skip
	SELECT * FROM X INNER JOIN Y ON true INNER JOIN Z ON false
because if we stringify it, we put the "ON true" in the wrong
place, and end up with something we can't parse.

The main change here is modifying AssertParseStatement and
AssertStatementStringer (and the corresponding Expression
functions) to also verify that they can clone and round-trip,
and that we can walk expressions. This gives us a ton
more coverage of Clone and conversions to string, and caught
a number of subtle typos and missing type switch cases.

Some of the changes are mostly cosmetic, such as only
including optional words when stringifying expressions
or statements if those optional words were present originally,
as shown by the Pos value stored for those words.

We also drop a lot of trailing apostrophes from some of the
parse test cases, which appear to be harmless but won't be
reproduced when converting back to strings.

We also add a number of additional test cases, or add
clauses to existing test cases, to improve coverage of a
lot of error testing. For instance, we added a decimal
field to the tests of show table, and added cases
using KEYPARTITIONS. (Although it doesn't *do* anything.)

Similarly, whenever we create a statement, we check
the behavior of requesting a list of sources from it, to
verify that source finding code at least runs.
2023-02-15 14:34:51 -06:00
Seebs
d6ec9649fc mark test helper as helper
If this fails, it'd be nice to know which invocation of it failed.
2023-02-15 14:34:51 -06:00
Pat Okeeffe
f205459003
fixed issue with interplay between count(*) and _id column (#2250) 2023-02-14 18:40:15 -06:00
Gregory Throne
6bf693b98c
docs migration link changes (#2247) 2023-02-14 17:28:08 -06:00
Bruce Baranowski
5c6361918a
FB-1862: Implement Str() scalar string function (#2215)
* Implement STR()
2023-02-14 15:58:36 -05:00
Pat Okeeffe
3dcc55203f
(fb-1903) - Fix SQL Fanout error (#2248)
* added some debug code

* added more logging

* do sql fanout on dedicated endpoint
2023-02-14 10:54:15 -06:00
Travis Turner
87011e4294
CLI: make it more like psql (#2235)
* Refactor CLI to mimic psql's meta-commands

This PR adds support for meta-commands (also known as "backslash
commands") like those in psql, Postgres's CLI. Only a few meta-commands
are currently implemented, but this was meant to demonstrate how we
could use something like `\i file.csv` to insert local files into SQL
statements.

* Meta-commands: \file and \include

The initial implementation used `\i` as a streaming file handle.

This commit changes that to `\file`, and then implements `\i` (or
`\include`) as handling multiple sql commands.

* Add meta-command "help" (\?)

This is basically a copy of the psql help output, but includes only
those options we currently support.

* Add support for \o [file], and \timing

The \o meta-command writes query output to a file.

The \timing meta-command turns on/off the timing display sent to stdout.

* Add meta-commands: \l (show databases) and \dt (show tables)

* Add meta-command: \watch [period]

* Update meta-command \connect to take database name instead of ID

* Add support for \echo, \qecho, and \warn

This commit contains an known issue in that the `-n` option will exclude
the line feed, but if the output is the terminal, the readline package
clobbers any content on the current line (i.e. anything without a line
feed). That will need to be addressed at some point.

* Add support for \w [FILE] (write query buffer to file)

* Add SchemaAPI no-op implementation

* Refactor query handler to align with /sql and /databases endpoints

We want to standardize on:
/sql
/databases/{databaseID}/sql

* Add CLI support for expanded, border, tuples_only (and pset)

* Add help text for \pset and \t
2023-02-14 09:23:51 -06:00
Pat Okeeffe
51f7a41e6c
handle empty strings as nulls for CSV (except for string types) (#2246) 2023-02-13 17:02:04 -06:00
Pat Okeeffe
4261c60a17
added test for inserts with timestamp + constraints (#2244) 2023-02-13 16:15:59 -06:00
Pat Okeeffe
5c74b64722
A bug fix roundup (#2242)
* fb-1940 re-implemented some changes that got missed private-public

* fb-1939 fixes to between + decimals

* fb-1935 - avg() on and id type + fixed some tests

* fb-1953 add min/max for string types

* fb-1938 - remove internal_type column from show columns

* fb-1964 - fix space_used in fb_cluster_nodes to be int

* fb-1996 - make sure all Idents that are being used as object references to schema objects are lowercased

* fixed failing test

* added some missed changes

* fb-1969 found another case issue with identifier used for column idents
2023-02-13 12:28:34 -06:00
Travis Turner
e803a000b8
Use the correct epoch when converting field.Options.Base to timestamp (#2241) 2023-02-10 17:13:09 -06:00
Travis Turner
bc450a91ea
Get rid of *most* of the context.Background() references in sql3 package (#2238)
* Thread context through sql3 DATABASE operations

* Get rid of *most* of the context.Background() references
2023-02-10 13:40:46 -06:00
Travis Turner
126be915a9
Support for setting individual DatabaseOptions (#2231)
* Implement Schemar.SetDatabaseOption(option, value string)

This replaces the temporary `SetDatabaseOptions()` method, which
replaced the entire DatabaseOptions struct, with `SetDatabaseOption`
which takes an option/value pair of strings to set.

* Add SetDatabaseOption to controller http handler and client

This commit also:
- renames some `writeLog` to `writelog`
- updates ApplyDirective to call resource.Unlock() on any resources
  being removed from the local worker

* Add Database related methods to SchemaAPI interface

Currently all implementations of this interface are implemented with
"unimplemented" errors on those methods. Next will be to implement the
necessary methods.

* SQL: CREATE DATABASE and SHOW DATABASES

* SQL: DROP DATABASE

* SQL: Add UNITS option to CREATE DATABASE

* SQL: ALTER DATABASE

* User serverlessStorage.Remove[*]Resource instead of resource.Unlock()

* Add WITH keyword to CREATE/ALTER DATABASE

* fix some WITH logic

* linter fixes

* WITH on CREATE DATABASE is not required
2023-02-06 08:50:28 -06:00
Matthew Jaffee
903e234c69
tweak a bunch of logging and config (#2234)
* tweak a bunch of logging and config

make overall logs less verbose and chatty

1 minute computer check-in interval

3 minute snapshot interval

remove CaptureLogger as it has same functionality as buffer logger

add a WithPrefix to the Logger interface so sub-services can have
different prefixes

* fix some lint

* fix lint... confused why this is coming up now
2023-02-03 14:59:07 -06:00
Matthew Jaffee
b43c4aabc5
move DD profiling/tracing setup into command where it belongs (#2233)
* move DD profiling/tracing setup into command where it belongs

* add url to http trace, use golang for container image
2023-02-01 16:20:39 -06:00
Fletcher Haynes
69331963da Updated version check to use POST only. Updated version check schema. Now generating a local UUID to submit to version check as a unique ID that persists in a file. 2023-02-01 08:28:28 -08:00
Travis Turner
20429bb9dc
Remove MDS and replace it with Controller (#2219)
* Remove MDS and replace it with Controller

This commit removes the MDS layer (and package) and shifts Controller
package into its place.

* add pprof/fgprof to serverless http router

---------

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2023-01-30 16:54:12 -06:00
HHans09
b12c90fdd1
Fb-1816 : CharIndex str func (#2216)
* rebased and updated

* Updates per review comments

Rebased

* Rebased

* Rebased
2023-01-30 16:08:46 -05:00
rachithrr
188b61b3cd
FB-1817: Implement FORMAT() (#2220) 2023-01-27 11:04:39 -06:00
tgruben
4e45f19ca0
parquet-info command to browse parquet files (#2230)
* parquet-info command to browse parquet files

* null support in parquet
2023-01-26 12:55:54 -06:00
tgruben
90e2808f52
bulk import support for parquet files (#2226)
* bulk import support form parquet files
2023-01-26 08:32:39 -06:00
Matthew Jaffee
49ef905b89
linter directive should not have space (dummy commit to trigger CI) (#2228) 2023-01-25 17:00:23 -06:00
Matthew Jaffee
a397501111
try to make sure we're releasing large allocations (#2225) 2023-01-25 14:48:01 -06:00
Pat Okeeffe
53cd483709
timestamp fixes (#2224)
* stop falling through a missing else + added test

* fix min and max on timestamp + tests

* address review feedback
2023-01-25 14:07:15 -06:00
Pat Okeeffe
d92ea8babf
hand comma version of inner join (#2221) 2023-01-25 13:37:05 -06:00
Matthew Jaffee
8f1f3c6d06
Fix pre sort cmd (#2222)
* make ndjson pre_sort parallel, fix several bugs, test

* remove json tags (not needed), rename pre_sort -> presort
2023-01-25 11:01:58 -06:00
Travis Turner
468461fbcf
Add Drop Database and Drop Table support (#2208)
* Support Drop Table in serverless (include Snapshotter, Writelogger)

* Finish Database methods

Things like:
- `Databases`
- `DatabaseByID`
- `DatabaseByName`
- `DropDatabase`

* Change Poller to use NodeService instead of its own map

Instead of the Poller maintaining its own map of Addresses to poll, this
commit changes the Poller to use the NodeService interface to get all
known nodes from the Controller.

The next commit needs to:
Next, the logic in the boltdb NodeService implementation was moved to
the boltdb Balancer implementation. That way, the Balancer can be the
source of truth for all things nodes/workers/jobs.

* Move NodeService from Controller to Balancer

This commit moves the implementation of the NodeService into the
Balancer, and aligns `Balancer.AddWorker` with `NodeService.CreateNode`
so that they stay in sync. (Same for `Balancer.RemoveWorker` and
`NodeService.DeleteNode`).

* fix import of private repo

* Fix go vet issues

* Fix bug in DeregisterNode

We need to remove the node from the NodeService even if it's not
assigned to a database. The logic had a bug in it.

This also adds some no-op implementations for SnapshotService and
WriteloggerService. If a directory was not configured for that, then the
computer node would panic on trying to read from the Snapshotter upon
receiving a Directive.

* queryer response content-type: json

* Add support for NULL to WriteloggerDir and SnapshotterDir configs

This commit changes the way WriteLoggerDir and SnapshotterDir are
handled.
If value is empty `""`, an error will be returned on computer startup.
If value is `"NULL"`, a no-op implementation of the service will be
used. This would be for a case that wanted to run serverless on-prem
with no durable storage.
Finally, any other value will be used as the directory to use.

Some things which aren't considered here and may result in unexpected
behavior:
- a value with spaces `" "`
- any "null" which is not "NULL"... like lowercase.

* Finish the DropTable test

* Change "disable service" value to case-insensitive "off"

This commit also removes an unnecessary sleep in the tests.

* Fix docker-compose variables for IDK test

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2023-01-23 19:59:47 -06:00
Pat Okeeffe
ad49fb174d
get fb_exec_requests underlying storage to use less memory (#2210)
* only keep the last 2000 requests and truncate sql and plan text to 4K each

* fixed import

* address review feedback

Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
2023-01-23 17:30:12 -06:00
Pat Okeeffe
bbca86d599
only turn a table scan into a PQL group by if it is a direct child of group by (#2217) 2023-01-23 16:49:31 -06:00
Pat Okeeffe
3606167758
handle float --> stringset implicit map conversion in bulk insert (#2211)
Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
2023-01-23 16:18:46 -06:00
Garrison Davis
f6baf32dbd Stop go test in GitHub CI
These tests are happening in GitLab CI instead.
2023-01-23 13:48:24 -07:00
Matthew Jaffee
6d4c1d9db1
Sup 294 pre sort command (#2209)
* first cut at pre-sort command that works on ndjson

* finish pre_sort command for CSV and JSON and add test

* try fixing golangci-lint

* remove some dumb lint checks

* more linter disabling

* take .golangci.yml from previous repo

* go fmt (facepalm)

* remove ioutil to fix lint
2023-01-23 12:26:38 -06:00
Garrison Davis
7bd62952d6 Add GitLab CI pipeline 2023-01-23 10:24:52 -07:00
Garrison Davis
39b2c97caa go mod tidy 2023-01-23 10:24:52 -07:00
Garrison Davis
c07727548d Stop using string keys in contexts 2023-01-23 10:24:52 -07:00
Travis Turner
6c0dcc126e
Merge pull request #2214 from FeatureBaseDB/tlt/fix-cli-exit
Fix CLI "exit" command
2023-01-21 16:49:07 -06:00
Travis Turner
cfbfee031b
Fix CLI "exit" command
When we added a line feed to the user input, we broke the check for
"exit" (because after that change we were getting "exit\n". This commit
moves the exit check before the line feed append.
2023-01-21 14:05:06 -06:00
Joseph Friedrich
ceb91cff51
Merge pull request #2207 from FeatureBaseDB/commit-sync-1-19-2022
Commit sync 1-19-2023
2023-01-19 20:19:26 -06:00
Joe Friedrich
7da67caa99 fix go deps, add lattice 2023-01-20 02:11:00 +00:00
Joe Friedrich
9d095ca6c2 Fixed controller import path 2023-01-20 01:06:54 +00:00
Joe Friedrich
c025daa226 Fixed dep paths 2023-01-20 01:01:18 +00:00
Joe Friedrich
82a398980d fix import sync "7f6ea0e6e..c38210bef" 2023-01-19 22:14:06 +00:00
Fletcher Haynes
15eafa9825 Add version checkin (#2413)
* Initial commit of code to do a version check-in on startup

* Add json tag to the response struct for version check

* Adjusted version check response types

* Changed error message in version check-in goroutine to use the logger. Changed URL to prod from dev.

* Updated version checkin URL to be analytics

Co-authored-by: Fletcher Haynes <fletcher.haynes@featurebase.com>
(cherry picked from commit c38210bef5)
2023-01-19 22:10:15 +00:00
Pat Okeeffe
b3a552e0d3 implement left join (fb-1888) (#2420)
* implement left join

* fixed failing test

(cherry picked from commit 7386f13159)
2023-01-19 22:10:15 +00:00
Jacob Brinlee
1046e28338 SUP-288 (#2414)
* adding kafka consumer config options (--kafka-max-poll-interval, --kafka-session-timeout,  --kafka-group-instance-id, --kafka-socket-keepalive-enable, and --consumer-close-timeout)

* wrapping consumer.Close() in timeout. Will wait consumer-close-timeout seconds before forcing consumer to exit

* clean up logs

(cherry picked from commit 17cdc58d80)
2023-01-19 22:10:15 +00:00
Travis Turner
f6a767befb Refactor CLI (#2417)
This commit moves the cli out of the `ctl` package and into its own
`cli` package. It also adds some basic tests for expected input.

Finally, it fixes a bug which was causing intentional line feeds to be
ignored, which was a problem with the BULK INSERT command.

(cherry picked from commit cf72bfa16f)
2023-01-19 22:10:15 +00:00
pokeeffe-molecula
f2812309ac make the count....count (#2416)
(cherry picked from commit b6e642338a)
2023-01-19 22:10:15 +00:00
HHans09
965ad15829 Fb 1876 : Implement Replicate() func (#2410)
* fb-1876 : creating Replicate fun

* fb-1876: creating string replicate func

* Fb-1876: String Replicate func

* Fb-1876: String Replicate func

(cherry picked from commit 2fccb87dcf)
2023-01-19 22:10:15 +00:00
Travis Turner
a9b3fd2c4d Database isolation: Balancer (#2407)
* Database isolation: Balancer

Remove naive Balancer

remove debugging lines

Thread dax.Transaction through Controller

Change role to roleType

Swap out Balancer interface with new one

Standardize InvalidTransaction error

Add some interface comments

* Remove type.Worker; replace with type.Address

* Remove database validate from Queryer

This is already being handled in the `CreateTable()` method. Prior
to doing that validation, we were getting a panic, but that's no longer
the case.

* Remove dax.TableQualifier; replace with dax.QualifiedDatabaseID

* Update IDK test to create database

(cherry picked from commit d971cfc269)
2023-01-19 22:10:08 +00:00
pokeeffe-molecula
5d025e399b implement CREATE/ALTER/DROP VIEW (fb-1592) (#2408)
* implement CREATE/ALTER/DROP VIEW

* fixed failing test

* another failing test

* fixed some broken serverless tests

(cherry picked from commit c620aae350)
2023-01-19 21:51:16 +00:00
rachithrr
fc1b8fdfb8 FB-1827: Implement Len() (#2406)
(cherry picked from commit f99be656df)
2023-01-19 21:51:16 +00:00
tgruben
adbad90fe1 string support for dataframe (#2405)
* String support for arrow

(cherry picked from commit 4cd3cb02a2)
2023-01-19 21:51:16 +00:00
pokeeffe-molecula
a1fc6d04a1 introduce performance counters and system table fanout, plus refactor metrics (#2363)
* performance counters

* first cut of perf counters and system table fanout and a wire protocol
* significantly refactored prometheus support; removed statsd and exprvar

* removed node_id

* put dax subquery test back

* Change Translator.TranslateFieldIDs method to take a dax.TableKeyer

There are a bunch of other calls to the Translator interface methods
with currently take an `index string`, and those need to be converted to
dax.TableKeyer as well. But I need to review each call, because in at
least one place I noticed one being called with `result.Index` instead
of with the qtbl available. And I don't yet know how those could be
different.

Co-authored-by: Travis Turner <travis@molecula.com>
(cherry picked from commit 7f6ea0e6e5)
2023-01-19 21:35:02 +00:00
Коrd Campbell
b6d290487d
update license to full license 2023-01-12 18:23:09 -06:00
Joseph Friedrich
61f9698082
Merge pull request #2201 from FeatureBaseDB/readme-doc-link-fixes
updated links in readme to point to latest pages in docs
2023-01-12 17:42:04 -06:00
Joseph Friedrich
5274caece8
Merge pull request #2204 from FeatureBaseDB/1-10-2023-cherry-pick
v3.27.0 cherry pick from private
2023-01-12 16:05:13 -06:00
Joe Friedrich
475bf58465 resolve go vet errors related to redeclares 2023-01-12 20:32:49 +00:00
Kord Campbell
3a7d6efcda add LICENSE 2023-01-12 09:18:35 -06:00
Joe Friedrich
48178064fe sync cherry-picks 4750c2215..17cb2cbb7 2023-01-12 00:59:13 +00:00
Joe Friedrich
fee6d8553a sync cherry-picks 4750c2215..17cb2cbb7 2023-01-12 00:58:33 +00:00
Коrd Campbell
e2c3b4008c fixes FB-1873 (#2400)
Co-authored-by: Kord Campbell <kord@Bob.local>
Co-authored-by: Fletcher Haynes <fletcher@capitalprawn.com>
(cherry picked from commit 17cb2cbb77)
2023-01-12 00:49:58 +00:00
pokeeffe-molecula
0ddf69a322 fix sum aggregate (fb-1874) (#2404)
* handle sum aggregates with ints; handle escaped quotes in blob literals

* added test ceoverage

* skip subquery test for dax

(cherry picked from commit af475a27f2)
2023-01-12 00:49:58 +00:00
rachithrr
1cdcaf472f FB-1814: Implement ASCII() (#2378)
* FB-1814: Implement ASCII()

(cherry picked from commit f590227471)
2023-01-12 00:49:58 +00:00
Julio Martinez
9030a054b7 Create main log with 640 permissions, leave all other logs the same. (#2402)
Co-authored-by: Julio <julio.martinez@featurebase.com>
(cherry picked from commit 3f91cc3dd1)
2023-01-12 00:49:58 +00:00
Julio Martinez
c23608557b Add dd tracer and associated config options (#2403)
Co-authored-by: Julio <julio.martinez@featurebase.com>
(cherry picked from commit 581a4d19a4)
2023-01-12 00:49:58 +00:00
Joe Friedrich
7acf3265ca fix import paths and import cycles 2023-01-12 00:31:14 +00:00
Joe Friedrich
77305b55ed fix indent 2023-01-11 19:29:01 +00:00
Joe Friedrich
d22bd9430f fix import paths 2023-01-11 18:59:24 +00:00
pokeeffe-molecula
3b1707c568 include space_used column in show table output (#2401)
(cherry picked from commit 4750c2215f)
2023-01-10 23:28:09 +00:00
Lory Cloutier
2b9c13497e Implement SPACE() function for SQL3 (#2399)
FB-1861

(cherry picked from commit da74f0a312)
2023-01-10 23:28:09 +00:00
pokeeffe-molecula
5e151eed0e handle insert into timequantum fields with default 'now' time (fb-1868) (#2398)
* handle insert into timequantum fields with default 'now' time

* allocate on the stack

(cherry picked from commit 18fe6a35f6)
2023-01-10 23:28:09 +00:00
Jacob Brinlee
3b233d271d adding more error handling for rbf (#2395)
* adding more error handling for rbf

Co-authored-by: Jacob Brinlee <jacobbrinlee@Jacobs-MBP.attlocal.net>
(cherry picked from commit c9ce26ce96)
2023-01-10 23:28:09 +00:00
pokeeffe-molecula
a6317c58e0 added space_used columns (#2397)
added space_used columns to show tables and fb_cluster_nodes

(cherry picked from commit 164aac509e)
2023-01-10 23:28:09 +00:00
pokeeffe-molecula
4e43b767df Bug fix round up (fb-1841, fb-1819, fb-1867) (#2396)
* check root operator after optimize

* round of bug fixes

(cherry picked from commit 9f042216a7)
2023-01-10 23:28:09 +00:00
Travis Turner
01cae92d96 Change JSON tag name on WireQueryResponse from execution-time to exec_time (#2394)
* Change JSON response name from exec_time to execution-time

Execution time stopped working in the CLI because it uses the latest
json tag.

* Wait, don't break the interface.

* Add a test for the sql response json tags.

This is to make sure that if someone like Travis just goes and changes a
tag name to be more consistent, that we perhaps catch that before it
gets to the end user.

* Change exec_time to execution-time after all

(cherry picked from commit b5dd3ea02e)
2023-01-10 23:28:09 +00:00
tgruben
5ec31d4159 [FB-1831] distribute bulk insert to owning node (#2391)
* distribute bulk insert to owning node

(cherry picked from commit e8505d8a53)
2023-01-10 23:28:09 +00:00
pokeeffe-molecula
74ee3ebf0e implemented DISTINCT (fb-1562) (#2388)
* implemented distinct

* implemented distinct
* uses first cut of a buffer pool, and extendible hashing with thresholded spill to disk
* tests
* cleaned up some stuff around query plan output to make developing tooling easier
* added optimization to call PQL Distinct()

* fixed test

* fix for passing wrong index name in orchestrator

* back out change to DistinctTimestamp

* fix other instance of wrong table name being passed

* use full index name instead of abbreviated one for translation. sigh.

* removed some unused code

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
(cherry picked from commit f030d58d95)
2023-01-10 23:28:00 +00:00
Matthew Jaffee
36f2dcce9e clean up TODOs. adds a control channel for on-demand snapshotting
(cherry picked from commit 4cc1667399)
2023-01-10 23:27:48 +00:00
Matthew Jaffee
e09a9dca47 first cut at removing all the shard/field/partition versioning
some cleanup needed

(cherry picked from commit bc9057f492)
2023-01-10 23:27:40 +00:00
Travis Turner
69a174412d Small adjustments to support the Serverless cloud merge (#2385)
This just changes a make target and the CLI setup. Nothing in
featurebase is actually affected.

(cherry picked from commit 33bc69ccc6)
2023-01-10 23:27:10 +00:00
Matthew Jaffee
0f67a0c432 first cut at automatic snapshotting
- had to make sure we don't snapshot until directive is fully applied
on a computer... otherwise there's races between loading the files and
truncating the write log.

- added a dirty bit to resources and a bool return to incrementing the
write log... don't snapshot if it returns false because that means
there's been no writes. (but make sure you close the storage transaction!)

- added the actually snapshotting routine which just fires every
<timeout> and serially snapshots everything.

- tweaked some logging

- added ability to get all tables in an org/db or literally all. I
think I just needed the "literally all", but it was natural to allow
it to be scoped to org or DB as well.

(cherry picked from commit b8b08bc9eb)
2023-01-10 23:26:29 +00:00
pokeeffe-molecula
f8120d4833 Consistency in error handling (fb-1799) (#2383)
* return 200 once plan compilation starts; if error, return error in response.

* removed some commented out code that is definitely not needed.

(cherry picked from commit 9dda3ff215)
2023-01-10 23:26:29 +00:00
Matthew Jaffee
dfd4bb1191 Expose translation mvcc (#2381)
* expose Transaction on TranslateStore for DAX Snapshotting

* try to fix ramdisk nonsense

apparently, we were running in either a shell env or docker env
randomly, so this could sometimes pass and sometimes fail since the
shell env had the ramdisk set up and docker didn't.

Now we force to run in docker always and set up ramdisk explicitly.

* debug ramdisk issue?

* fix tests... and a buncha other stuff

The executor test I modified failed when I changed DefaultPartitionN
to 8, but just because stuff was out of order so I made it more
robust.

I edited some data gen stuff to make shorter lines because it was
making grep results unusable.

the actual fix is in translate_boltdb_test.go

* clean up, fix code review feedback

(cherry picked from commit 3693b9950a)
2023-01-10 23:25:58 +00:00
pokeeffe-molecula
a6c165dd57 Implement DELETE (fb 1557) (#2382)
* delete implementation with test coverage

* optimize IN expressions; stop linter complaining

* fixed some uncovered query cases

* skip test in DAX for now

(cherry picked from commit 021219935f)
2023-01-10 23:25:08 +00:00
Bruce Baranowski
36c020f076 Fb 1818 Implement PREFIX() and SUFFIX() (#2371)
* Implement Prefix and Suffix
* Update substring out-of-index handling

(cherry picked from commit d19f3e81da)
2023-01-10 23:25:08 +00:00
tgruben
427f7a4494 Force make to use bash (#2380)
(cherry picked from commit 72d03602e0)
2023-01-10 23:25:08 +00:00
Matthew Jaffee
a9b248bb29 "fix" backup tar test by just comparing lengths not byte for byte
(cherry picked from commit 1e2e698225)
2023-01-10 23:25:08 +00:00
Matthew Jaffee
71c0624abb remove in mem translate store
(cherry picked from commit 7ab117f5d1)
2023-01-10 23:23:18 +00:00
Matthew Jaffee
da4a42dfe9 use separate qcx for write/read in test
now that min/max queries don't use a write Tx it seems we need to
separate read and write in the tests. Not sure I 100% understand this.

(cherry picked from commit a58299def4)
2023-01-10 23:22:58 +00:00
Matthew Jaffee
da85614c24 set transactions to writable: false for Max/Min/Value calls. these were mistakenly set to true during cleanup
(cherry picked from commit 53a8f58e91)
2023-01-10 23:22:58 +00:00
tgruben
24372a9405 [FB-1822] Change dataframe disk format to Arrow from parquet (#2376)
* change default backend to arrow file format instead of parquet

(cherry picked from commit 6d96a1474e)
2023-01-10 23:22:58 +00:00
Fletcher Haynes
2993ab5ca1 This fixes a bug with displaying errors returned from the SQL3 endpoint (#2374)
Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
(cherry picked from commit f65367ab46)
2023-01-10 23:22:58 +00:00
Lory Cloutier
5f15d3ad10 Fix bulk ingest queries on multi-node databases (#2375)
CLOUD-1252
Implemented Jaffee's fix of checking for b.useShardTransactionalEndpoint
and only running the start/finish transaction block if it's false. Moved
stats timing to a separate defer so it could stay out of the if.

(cherry picked from commit b1f5264a4b)
2023-01-10 23:22:58 +00:00
rachithrr
4aa34d3e1c FB-1815: Implement CHAR() (#2369)
(cherry picked from commit 27963441ab)
2023-01-10 23:22:58 +00:00
Travis Turner
99e3fd14d7 Fix PQL distinct in dax (#2360)
* Fix PQL distinct in dax

When issuing a PQL Distinct() call (or any other call with a "index=" arg),
this commit will attempt to convert the value in the index arg with a
TableKeyer.

* Apply change to call.Children as well

* Add some PQL Distinct (join) test coverage

(cherry picked from commit 4e8fe488de)
2023-01-10 23:22:58 +00:00
pokeeffe-molecula
211c3b759d add allow_missing_values option to bulk insert (fb-1823) (#2372)
* add allow_missing_values option to bulk insert

* test coverage

* review feedback

(cherry picked from commit 15d2ee8b07)
2023-01-10 23:22:58 +00:00
pokeeffe-molecula
bb2c805cac handling missing epoch constraint correctly (#2366)
(cherry picked from commit 843312dfc9)
2023-01-10 23:22:58 +00:00
pokeeffe-molecula
f42a33640a enable handling string representations of integers (#2367)
(cherry picked from commit 3528ec8fc0)
2023-01-10 23:22:58 +00:00
pokeeffe-molecula
4ef70c19da SHOW CREATE TABLE issues (fb-1810) (#2365)
* fixed ddl issues with cache type/size; removed shardwidth option; improved error message

(cherry picked from commit c88d60c9ab)
2023-01-10 23:22:58 +00:00
Matthew Jaffee
f6c0cf1112 rename stupid manager names
ManagerManager -> ResourceManager
Manager -> Resource

(cherry picked from commit 033be81799)
2023-01-10 23:22:58 +00:00
Matthew Jaffee
0e8773707a code review tweaks
(cherry picked from commit cf1c9dae9a)
2023-01-10 23:22:58 +00:00
Matthew Jaffee
9a441ef66b remove version/directive stuff from other snapshot endpoints
(cherry picked from commit 4366ad41fb)
2023-01-10 23:22:58 +00:00
Matthew Jaffee
41b865d838 clean up unused code/comments
(cherry picked from commit 3ddf79160f)
2023-01-10 23:22:54 +00:00
Matthew Jaffee
4d678faa72 fix dumb issue on storage manager test
changed empty snapshots/writelogs to return nil which was causing NPE

(cherry picked from commit bee666c07c)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
bc3123ddd4 fix lint
(cherry picked from commit 797b8bc31f)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
6cef68a853 several fixes and debug logging
- check that serverlessStorage is not nil before closing it
- check that we don't already hold a lock on a serverless storage
  Manager before trying to load it. This fixed at least one test failure.

(cherry picked from commit 87d1c31607)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
76682753da implement closing on dax, remove all locks when shutting down
(cherry picked from commit dbb6d53f9d)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
ff3595d759 more WIP
(cherry picked from commit bbaa7dd0f1)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
ed7c6d419e extremely WIP
(cherry picked from commit 35c472a54f)
2023-01-10 23:22:03 +00:00
Matthew Jaffee
71e3c00b46 remove alpha director (unused)
(cherry picked from commit 690a9370e9)
2023-01-10 23:21:58 +00:00
rachithrr
e8ac1a0a7f FB-1812: implement stringsplit() (#2362)
(cherry picked from commit a4f18fb25f)
2023-01-10 23:21:31 +00:00
HHans09
766db38277 fb-1809: SQL3 RTrim & LTrim func for strings (#2361)
(cherry picked from commit c1dbc48fb2)
2023-01-10 23:20:52 +00:00
pokeeffe-molecula
b46a82ea33 added updated_at column to show tables output (#2364)
(cherry picked from commit 9759602f94)
2023-01-10 23:20:15 +00:00
pokeeffe-molecula
75999414a7 implement having; create view experiment (#2357)
(cherry picked from commit eca3168d63)
2023-01-10 23:20:15 +00:00
Bruce Baranowski
838bc2dadb FB-1719: implement SQL3 lower() (#2358)
* Implemented SQL3 LOWER()

(cherry picked from commit 4773aabc4e)
2023-01-10 23:20:15 +00:00
Lory Cloutier
748fdc3741 Prevent file corruption when writing tar backup to stdout (#2344)
* Prevent file corruption when writing tar backup to stdout

FB-1794

Tar backups written to stdout were coming out corrupt. This turned
out to be due to log messages getting written to stdout and ending
up in the tar file. We now check to see if the tar file and the log
are both going to stdout, and if they are, send the logs to stderr
instead.

Testing did not have any kind of consistency or validity check. We
now compare a tar file sent to a file and a tar file sent to stdout
to make sure they're the same. This does not guarantee correctness
but does at least catch this form of corruption.

* trying different index name

Co-authored-by: tgruben <tgruben@gmail.com>
Co-authored-by: Todd Gruben <todd@molecula.com>
(cherry picked from commit a8996a149d)
2023-01-10 23:20:15 +00:00
pokeeffe-molecula
f2442dcd88 fixed csv bugs (#2355)
(cherry picked from commit 2146f407c3)
2023-01-10 23:20:15 +00:00
Travis Turner
9e2dbadb82 Fix dax docker-compose (dc-up) which was broken by ServiceManager (#2356)
(cherry picked from commit e572c8f2c1)
2023-01-10 23:20:15 +00:00
tgruben
a2e14df15c Fb 1874 dataframe-csv-loader featurebase subcommand (#2341)
Embeded dataframe-csv-loader command as featurebase subservice

(cherry picked from commit f2a13c8bde)
2023-01-10 23:20:15 +00:00
HHans09
80626df411 fb-1802 : Trim functionality (#2353)
* fb-1802 : Trim functionality

rebase

* fb-1802 : trim - updated as per review

(cherry picked from commit ac3ffac8e6)
2023-01-10 23:20:15 +00:00
Travis Turner
20d7361566 Make interfaces more specific than "MDS" (#2352)
* Make interfaces more specific than "MDS"

- Introduce `dax.Schemar` interface
- Introduce `dax.Noder` interface
- The rest is generally to standardize on the new interfaces.
- Remove `pilosa.SchemaInfoAPI` interface
- Move `TranslateNode` and `ComputeNode` types from controller to dax package
- Remove `queryer.FeatureBaseImporter`
- Remove `queryer.MDS` interface
- Remove `queryer.Importer` interface
- Identify types using an "MDS" interface and split into Noder/Schemar as necessary
- Changed `Queryer.orchestrator` to a `map[qual]*qualifiedOrchestrator` because we can't share an orchestrator across quals

* Convert orchestrator to use TableKeyer

(cherry picked from commit 14f1930004)
2023-01-10 23:20:10 +00:00
Travis Turner
0127147d69 Thread Owner, UpdatedAt, UpdatedBy through SchemaAPI (#2351)
* Fix "qualifer" misspellings

* Remove `track_existence` and `shard_width` from SHOW TABLES output

* Thread Owner, UpdatedAt, UpdatedBy through SchemaAPI

I took the liberty of renaming "LastUpdatedUser" to "UpdateBy" to align
with "UpdatedAt".

(cherry picked from commit 63cfdb5078)
2023-01-10 23:19:19 +00:00
rachithrr
17188b7a7b FB-1805: implement REPLACEALL() (#2349)
(cherry picked from commit 9548e71f46)
2023-01-10 23:19:19 +00:00
Travis Turner
3ee936ebc8 Introduce TableKeyer interface; use in Execute() calls as "index" (#2350)
This commit introduces an interface called `TableKeyer` which anything that means to represent a "table"
can implement. Examples are `dax.QualifiedTable`, `dax.Table`, and `string` (for legacy pilosa calls
where Execute simply took `index string`).

In the case of `orchestrator.Execute()` and `qualifiedOrchestrator.Execute()`, we are intentionally strict
about which type of `TableKeyer` the respective method accepts. If we find, in the future, this is too
restrictive, we can loosen that; but for now it helps us understand what is expected.

(cherry picked from commit a61d1a9571)
2023-01-10 23:19:19 +00:00
Travis Turner
0cb16f0cf4 Remove trackExistence check in batch (i.e. always build _exists) data. (#2348)
(cherry picked from commit 5110405f2f)
2023-01-10 23:19:19 +00:00
Travis Turner
c7b4e47f10 Move batch.Importer interface to pilosa.Importer (#2347)
* Move batch.Importer interface to pilosa.Importer

In addition to moving the interface, it updates all the methods to use
dax.TableID (for example) intead of a string pilosa index name.

* Change unused onPremImporter methods to no-op.

onPremImporter is a wrapper around API which implements the Importer
interface. This is currently only used by sql3 running locally in standard
(i.e not "serverless") mode. Because sql3 always sets
`useShardTransactionalEndpoint = true`, There are several methods which this
implemtation of the Importer interface does not use, and therefore they
intentionally no-op.

(cherry picked from commit 12d608c80d)
2023-01-10 23:18:59 +00:00
HHans09
9346e26158 Fb:1787 - Clean up (#2339)
* Fb:1787 - Clean up

* fb-1787 : String upper function

* Formatting the files

(cherry picked from commit 57ce7c4c0e)
2023-01-10 23:18:38 +00:00
Travis Turner
c4532124e1 Add Table.Description, Table.CreatedAt, Field.CreatedAt support to SchemaAPI (#2340)
* Thread Table.Description through SchemaAPI

* Thread Table.CreatedAt through SchemaAPI

* Thread Field.CreatedAt through SchemaAPI

(cherry picked from commit 734477aaee)
2023-01-10 23:18:32 +00:00
rachithrr
c39e599086 FB-1800: Implement SUBSTRING() (#2343)
substring(string, startIndex,length).

(cherry picked from commit aa2a62fda0)
2023-01-10 23:18:19 +00:00
pokeeffe-molecula
eb54530de6 handle int-->bool map type conversions; handle single value-->(id|string)set map type conversions (#2342)
(cherry picked from commit 728b1dc9f5)
2023-01-10 23:18:07 +00:00
Fletcher Haynes
2020cef8ac This adds in support to the lattice UI application to use the SQL3 (#2338)
* This adds in support to the lattice UI application to use the SQL3
endpoint. If the `/sql` endpoint returns 404, it will use the SQL1
endpoint. If the `/sql` endpoint is available, it will send SQL queries
to that. It does not try the SQL1 endpoint if the SQL3 endpoint returns
an error processing the query. That is, it is all SQL3 or SQL1.

- Below are the specific changes:
- Adds a file that contains functions for interacting with http services as opposed to just grpc/event-based services. As of this commit, it is only the SQL3 endpoint.
- This adds a variable to track if we are using the SQL3 endpoint or not
- This adds a function to handle the response from the SQL3 endpoint
- Adds a function to eventServices to query the sql3 HTTP endpoint
- Fixed a missing semicolon in grpcServices

Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
(cherry picked from commit 7ab453e289)
2023-01-10 23:17:53 +00:00
Travis Turner
0985eeb9b1 Convert SchemaAPI interface to use dax.Table instead of pilosa.IndexInfo (#2336)
* WIP: Convert SchemaAPI to be DAX-centric

* Tables(), CreateField()

* CreateTable(), DeleteTable(), DeleteField()

* More cleanup

* Remove the old SchemaAPI

(cherry picked from commit a15783cb49)
2023-01-10 23:17:26 +00:00
rachithrr
a74b5c7008 FB-1795: Implement REVERSE() scalar string function (#2335)
(cherry picked from commit d33bf4811f)
2023-01-10 23:16:48 +00:00
pokeeffe-molecula
58ff14441a
updated links in readme to point to latest pages in docs 2022-12-29 10:34:34 -06:00
Fletcher Haynes
5c39a49285 Sync from private repo to commit 12d608c80d 2022-12-12 09:01:20 -08:00
Travis Turner
5c76ad5e70 Move batch.Importer interface to pilosa.Importer (#2347)
* Move batch.Importer interface to pilosa.Importer

In addition to moving the interface, it updates all the methods to use
dax.TableID (for example) intead of a string pilosa index name.

* Change unused onPremImporter methods to no-op.

onPremImporter is a wrapper around API which implements the Importer
interface. This is currently only used by sql3 running locally in standard
(i.e not "serverless") mode. Because sql3 always sets
`useShardTransactionalEndpoint = true`, There are several methods which this
implemtation of the Importer interface does not use, and therefore they
intentionally no-op.

(cherry picked from commit 12d608c80d)
2022-12-12 09:01:20 -08:00
HHans09
682f240b7b Fb:1787 - Clean up (#2339)
* Fb:1787 - Clean up

* fb-1787 : String upper function

* Formatting the files

(cherry picked from commit 57ce7c4c0e)
2022-12-12 09:01:20 -08:00
Travis Turner
830b2ab4c8 Add Table.Description, Table.CreatedAt, Field.CreatedAt support to SchemaAPI (#2340)
* Thread Table.Description through SchemaAPI

* Thread Table.CreatedAt through SchemaAPI

* Thread Field.CreatedAt through SchemaAPI

(cherry picked from commit 734477aaee)
2022-12-12 09:01:20 -08:00
rachithrr
12ff18bc55 FB-1800: Implement SUBSTRING() (#2343)
substring(string, startIndex,length).

(cherry picked from commit aa2a62fda0)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
40d292b589 handle int-->bool map type conversions; handle single value-->(id|string)set map type conversions (#2342)
(cherry picked from commit 728b1dc9f5)
2022-12-12 09:01:20 -08:00
Fletcher Haynes
bf0486503a This adds in support to the lattice UI application to use the SQL3 (#2338)
* This adds in support to the lattice UI application to use the SQL3
endpoint. If the `/sql` endpoint returns 404, it will use the SQL1
endpoint. If the `/sql` endpoint is available, it will send SQL queries
to that. It does not try the SQL1 endpoint if the SQL3 endpoint returns
an error processing the query. That is, it is all SQL3 or SQL1.

- Below are the specific changes:
- Adds a file that contains functions for interacting with http services as opposed to just grpc/event-based services. As of this commit, it is only the SQL3 endpoint.
- This adds a variable to track if we are using the SQL3 endpoint or not
- This adds a function to handle the response from the SQL3 endpoint
- Adds a function to eventServices to query the sql3 HTTP endpoint
- Fixed a missing semicolon in grpcServices

Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
(cherry picked from commit 7ab453e289)
2022-12-12 09:01:20 -08:00
Travis Turner
4e3856348c Convert SchemaAPI interface to use dax.Table instead of pilosa.IndexInfo (#2336)
* WIP: Convert SchemaAPI to be DAX-centric

* Tables(), CreateField()

* CreateTable(), DeleteTable(), DeleteField()

* More cleanup

* Remove the old SchemaAPI

(cherry picked from commit a15783cb49)
2022-12-12 09:01:20 -08:00
rachithrr
e33426d0cf FB-1795: Implement REVERSE() scalar string function (#2335)
(cherry picked from commit d33bf4811f)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
5e28a3424c you should be able to cast an id as a string (#2334)
(cherry picked from commit e599f12ee4)
2022-12-12 09:01:20 -08:00
rachithrr
891a42f9fc FB-1739: Add ability to add a description to a table on creation (#2332)
* FB-1739: Add ability to add a description to a table on creation

- Added CommentOption to handle text after COMMENT option.
- added description field in the createtable plan.
- The description is stored in the existing index metadata.

(cherry picked from commit ad350c2d49)
2022-12-12 09:01:20 -08:00
Travis Turner
ce32a1bde6 Rename some interfaces. Remove the ComputeAPI (#2333)
* Clean up dax service interfaces

Rename some of the `computer` interfaces and organize them in the
appropriate files.
Remove `dax/computer/alpha` package

* Remove ComputeAPI (it was replaced by batch.Importer)

* add nss-tools dependecy to smoke test

(cherry picked from commit 969bf055b2)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
8fab5239b8 handle decimal without scale correctly; handle bulk insert dupe columns correctly; handle decimal->string & float->string type conversions in bulk insert (#2331)
(cherry picked from commit d2eba5bd8d)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
c439d53584 enforce int min/max constraints on insert (fb-1772) (#2325)
* moved the debug code to the right spot

* enforce int min/max constraints on inserts

* add a check for decimal min and max

* fixed borked tests

* fix the decimal to int conversion in constraint check

Co-authored-by: Travis Turner <travis@molecula.com>
(cherry picked from commit e392ce3460)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
c304991e9f implemented extract ddl; tightened up type related stuff (#2329)
* implemented extract ddl; tightened up type related stuff

* added some test coverage

* review feedback

(cherry picked from commit f62313762c)
2022-12-12 09:01:20 -08:00
Travis Turner
a44b622aa0 Introduce ServiceManager and Refactor DAX Integration tests (#2320)
* Introduce ServiceManager and Refactor DAX Integration tests

The ServiceManager provides an interface with which to manage
featurebase (dax) services (mds, queryer, computer). It replaces the
confusing interface implementations in /dax/server/server.go (which
optionally used pointers to in-process objects to satisfy an interface)
with (for now) http implementations. The thought is that even if we're
running all services in-process, we should communicate between services
over http in order to mirror what we would do in a production
environment where the services are running on different nodes.

This batch of commits does quit a lot, most of which is captured here:

- Added `path` support to `dax.Address`. Address is now a string of the form [scheme]://[host]:[port]/[path].
- Added `Holder.directiveApplied` to determine (in tests) if the computer has completed applying the latest directive. This is somewhat temporary until we improve the mds-to-computer logic.
- Removed the "service prefix" code which was prepending client URL paths with the prefix. Instead, the serviceType (mds, queryer, computer[n] is now part of `dax.Address`).
- Removed, from the dax config, the top level `StorageMethod` and `StorageDSN` and now just have `MDS.Config.DataDir`.
- Added `Computer.Config.N` to specify the number of computers to run in-process.
- Moved the `pilosa.MDS` interface to `computer.Registrar`. This is an example of getting the interfaces defined in the right packages.
- Added `SnapshotTable()` method to the mds client (to align with its API).
- Changed `Balancer.AddJob()` to `Balancer.AddJobs()` to support, for example, adding 256 partitions in a single call. Refactored some of the naive Balancer to account for this.
- Added a `Seed` to the top-level config. It's not really useful because of package `crypto/rand`.
- Added an in-memory implementation of the DisCo interface and disabled etcd in a computer service.
- Create sepearte data-dirs for each in-process computer.
- Disabled grpc in dax.
- Modified the sql3 test definition format to support multiple insert steps and separate query results (to align with those steps).

* Changes necessary to get multiple computer instance running in-process

For now the config looks like this:

```
[computer]
run = true
n = 4
```

but we can probably just change that to be something like:

```
[computer]
run = 4
```

*Issues found running multiple "computers" in-process*
- grpc was trying to bind on the same port
  - changed GRPCListener from `*net.TCPListener` to `net.Listener`
  - created a nopListener and set to that for now (i.e. disabled grpc)
- etcd was starting more than once
  - changed dax to use in-memory implementations of the disco interfaces (i.e. stop using etcd)
- IDAllocator (which uses boltdb) was trying to open the `idalloc.db` file more than once
  - realized we have to set separate data-dirs for each holder. that fixed it.

* Port dax integration tests to ManagedCommand

* Modify Balancer-related methods like AddJob to AddJobs

There were (and still are) a lot of places where we were adding on job
at a time, even when we had a long list of jobs to add. This resulted in
every job add (for example adding 1 of 256 shards) taking ~40ms, or over
10s to create a keyed table. One reason was because each job add was
making multiple boltdb transactions.

* Port over more dax integration test stuff

* Add DirectiveApplied to signify that snapshot/writes have loaded.

We use this in tests to avoid using sleeps.
This should be considered temporary; we're going to need a more robust
solution for determining when a computer node is ready to serve complete
data.

* Finish porting dax integration tests

* Improve godocs

* Remove docker-based DAX integration tests.

* go mod tidy

* Move test/managed.go to avoid package conflicts

* Modify IDK integration tests to work with ServiceManager changes

This is really just computer -> computer0
And the MDS DataDir config change.

* cleanup found during review

* echo $CI_COMMIT_REF_SLUG in CI

* remove docker image arg, use build instead

(cherry picked from commit 2843f218bc)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
d6d5ddb501 non-sql aggregation, top, decimal and sundries (#2328)
* fixed a bunch of issues with non-pql aggregation; moved some decimal related functionality; made top actually top (for the non-pql case); experimental create function

* drive up test coverage

(cherry picked from commit 0be0c42b66)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
dca0dd84e3 implement fb_exec_requests system table (#2327)
implements an fb_exec_requests system table. The purpose of this table is to allow access to internal state to see what queries are running and have been run.
Co-authored-by: Travis Turner <travis@molecula.com>

(cherry picked from commit 47d8be26f5)
2022-12-12 09:01:20 -08:00
Garrison Davis
daf6e29b02 Make SOURCE_DATE_EPOCH changes for idk
(cherry picked from commit be619fa60d)
2022-12-12 09:01:20 -08:00
Garrison Davis
d0ea451bcc Use SOURCE_DATE_EPOCH to make reproducible builds
Reproducible builds are something we should be doing, and we are there
as far as making them in CI is concerned with this change.

The changes to the Dockerfile/Makefile do nothing if the
SOURCE_DATE_EPOCH environment variable is not set before `make build`
happens, or if the build arg is not passed in to docker.

(cherry picked from commit fd93fc99c9)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
c210aaba48 produce a better error when a user tries to sort something unsortable (#2324)
(cherry picked from commit 1ce3a1c103)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
aaf963c9bd (fb-1779) make optimizer smarter with top operators and aggregate queries (#2323)
* updated optimizer to be smarter when trying to push a top operator down; added test coverage

* skip a dax sql test that keeps failing

(cherry picked from commit e0d6b292bc)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
11aaeb72b4 fixed error messages for alter table add and drop; added test coverage (#2322)
* fixed error messages for alter table add and drop; added test coverage
* Removed two CI tests that are failing intermittently for no known reason.

(cherry picked from commit 3c2c8c6011)
2022-12-12 09:01:20 -08:00
Lory Cloutier
5693767ba2 Don't use reflect.DeepEqual to compare errors.
FB-1771

In api_test.go, it was being used to make sure that incorrect input
produced the right errors; this is now handled by making sure the
error isn't nil and then checking its string against the expected
error string.

In executor_test.go and internal_client_test.go, it was being used
to compare QueryResponse structures, which contain an error.
handler.go now has a function specifically for comparing them,
which can provide additional detail if necessary.

Added a test for SameAs to handler_test.go.

(cherry picked from commit 775fd0b08c)
2022-12-12 09:01:20 -08:00
tgruben
ab4ce354c4 [FB-1776] support for marshaling ExtractedIDMatrixSorted (#2319)
support for marshaling ExtractedIDMatrixSorted

(cherry picked from commit 04b19c066a)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
eae8376181 Tighten up ORDER BY (fb 507) (#2318)
* tighten up checks for order by expressions fixed ordering by expressions

* added testing to cover order by cases

* Add DecimalAgg member to proto GroupCount definition

In DAX, where we have split the orchestrator from the executor, and the
orchestrator can run on a different host, there are cases where
`GroupCount`s can travel over the wire via the Internal Client. In these
cases, when the group count contains a decimal aggregate, we need to
send that value as the appropriate type.

* fixed missing cases in order by and case block eval

Co-authored-by: Travis Turner <travis@molecula.com>
(cherry picked from commit 158cc669d9)
2022-12-12 09:01:20 -08:00
Lory Cloutier
b6ae088f24 FB-1766: cleaning up the CmdIO objects passing alternate stdin/
stdout/stderr around

A lot of functions in the cmd and ctl packages were passing these
around and barely using them. Replaced them with a logger for most
functions. Some functions get an io.Writer instead so that their
tests can find the output they're looking for.

More cleanup on fb-1766: reworked the tests that were using io.Pipe
or os.Pipe to check their results so they now use a bytes.Buffer.

Unexported some variables that didn't need to be exported.
Fixed NewConfigCommand to use the provided stderr, not os.Stderr.
Added tests for rbf_dump, rbf_page, and keygen, since those weren't
being tested at all.

Added chksum_test, final cleanup.

(cherry picked from commit f627199acb)
2022-12-12 09:01:20 -08:00
tgruben
fa162d16cc upgrade to immutable 0.4.0(generics) (#2317)
(cherry picked from commit a98b9144cb)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
41e231504e handle filters on _id columns (fb-1765) (#2313)
* handle filters on _id columns using ConstRow
* handle keyed and un-keyed _id columns
* tests!

(cherry picked from commit df829c592f)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
0bd17d6185 fixed top(x) where top cannot be pushed down into pql query (#2311)
* fixed top(x) where top cannot be pushed down into pql query

* review feedback

(cherry picked from commit d3f10be743)
2022-12-12 09:01:20 -08:00
Travis Turner
b700346a1f Fix more of the SQL tests in dax (#2310)
There are now only four tests remaining which do not pass.

One is related to error format mismatch.
Two require orchestrator work.
One won't pass until table name conversion is supported for multiple
tables.

(cherry picked from commit 5bf5b5364d)
2022-12-12 09:01:20 -08:00
Travis Turner
e2758005cb Prepend header bytes to WriteLog messages for backward compatibility (#2309)
MarshalLogMessage serializes the log message and prepends additional encoding
information to each message. Currently, we prepend three bytes to each log
message:
byte[0]: encodeVersion - this is currently a constant within the code. If we
modify structs such that they encode differently, we'll have to change the
constant and keep previous versions of structs for deserialization.
byte[1]: encodeType (e.g. "json", etc.)
byte[2]: logMessageType

If we get into a situation where we want more flexibility in these message
header bytes—for example, if we want to use more than three bytes—we could do
something with the first bit of the encodeVersion: if it's 1, that could
indicate that there are additional header bytes, and the following seven bits
could indicate how many.

(cherry picked from commit 6740bc250e)
2022-12-12 09:01:20 -08:00
Travis Turner
444d4804ec Fix formatting in CLI results with custom SQLResonse.UnmarshalJSON (#2305)
* Fix formatting in CLI results with custom SQLResonse.UnmarshalJSON

When I started this, it was meant to be a quick fix to address the confusing
result formats we were seeing in the CLI. For example, all large integer values
were displayed in scientifc notation. This is because we were passing the result
types from JSON (in this case, float64) into pretty print. Similarly, `IDSets`
and `StringSets` where being printed using the default go Stringer for the types
[]int64 and []string respectively.

I started by writing a customer UnmarshalJSON() method for the `SQLResponse`
type. Part of this (the part which converts data types based on header types)
was already being used in dax tests, so this just formalizes that logic as part
of the `SQLResponse` type.

Then I realized that the sql3 tests (run against the `sql3` package) were
failing because sql3 is not actually returning the `IDSets` and `StringSets`
types. A future task is to formalize return types, define them, and modify sql3
to return them. Once that is done, we can remove the "typed" switch in the
`SQLResponse` json unmarshaller.

Another significant change is the modification to the `ExprDataType` interface:
```
type ExprDataType interface {
	exprDataType()
	TypeName() string
	TypeDescription() string
	TypeInfo() map[string]interface{}
}
```
I added two more methods in order to distinguish between a type (`DECIMAL`), its
description (`DECIMAL(2)`), and its type info (`"scale": int64(2)`). Currently,
the description can be used as the field definition in a CREATE TABLE statement,
but we may want to re-think that. Also, Decimal is the only type currently using
TypeInfo.

Finally, I tried to consilidate things around `dax.FieldType` instead of
comparing against parser types outside of sql3. We still have some sql3 parser
and planner types lurking about, but we can address those in future commits.

* Add some test coverage

* smoke test expected INT, now int

* minor fixes

* Introduce WireQueryResponse and related types

This also changes dax.FieldType to dax.BaseType.

* Populate WireQueryResponse correctly

Currently this is in the http handler, and in the queryer.

* Convert sql3 and dax tests to expect pilosa.WireQueryField in results

* fix PQL tests in the SQL defs

* Address a few of the skipped sql tests in dax

(cherry picked from commit f4385df2cf)
2022-12-12 09:01:20 -08:00
tgruben
2fc7abd72e Dataframe (#2241)
* Dataframe

(cherry picked from commit 2f1beaf119)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
e2500fcee8 Fb 1767 (#2308)
* identifiers can now have the '-' character
* skip some integration tests

(cherry picked from commit cca319fbe5)
2022-12-12 09:01:20 -08:00
pokeeffe-molecula
b17ee6a203 fixed join bugs by fixing query optimizer (fb-1699, fb-1700) (#2307)
this commit changes the way the plan is retrieved; implements Stringer on types.PlanExpression in preparation for HAVING support; removes last vestiges internal float64 arithmetic; implements a filter on PlanOpFilter; fixes various bugs in the PlanOptimizer when rewriting qualified references

* fixed selects with unqualified identifiers

* handle bad and non-existent query param inputs more appropriately

* added test coverage for PlanExpression Stringer

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
(cherry picked from commit 5f662d2bce)
2022-12-12 09:01:20 -08:00
Travis Turner
cd260fe665 Make sure table stub is valid as a pilosa.Index name (#2306)
We use part of the dax.TableName in the pilosa.Index.Name.
This just ensure that we don't let invalid characters get through.

(cherry picked from commit 10e8aa5c45)
2022-12-12 09:01:20 -08:00
Kord Campbell
b468da449f fixes FB-1768, two entries for the holder command
(cherry picked from commit 875c7492fe)
2022-12-12 09:01:20 -08:00
Seebs
f06b187bbd improve coverage in tests
(cherry picked from commit bd2b9ac225)
2022-12-12 09:01:20 -08:00
Seebs
f2d1c3f459 write header before body
This produces an http warning that doesn't make the test fail.

(cherry picked from commit d0ccf8e4e4)
2022-12-12 09:01:20 -08:00
Seebs
1009fa4164 actually honor provided stdin/stdout
the BackupTar and RestoreTar functionality was ignoring provided
readers, which doesn't matter for real usage but breaks tests
by making them dump raw tar binaries to stdout.

(cherry picked from commit 93153a97db)
2022-12-12 09:01:20 -08:00
Seebs
3c05f1ff37 Distinguish between usage errors and other errors
Cobra automatically displays usage messages, and also a gratuitous
"Error: [...]" line in some cases, when any error at all occurs
running a command. To suppress the usage message, you have to set
cmd.SilenceUsage to true. But the code that would do this doesn't
have access to it. To address this, we introduce a category of
"usage error", implemented with stdlib error wrapping (%w) and
use errors.Is to check for it. There's also utility functions
to do this checking automatically, or indeed, to handle wrapping
of the ctl.SomethingCommand and handle running it with a suitable
context and everything.

In fact, several of the places we're checking for usage errors,
we can never actually report one, but we're checking consistently
so that if we want to report usage errors, we can.

For instance, server.Start and (dax)server.Start don't ever
return usage errors, right now, but we're checking their responses
anyway.

(cherry picked from commit c681642734)
2022-12-12 09:01:20 -08:00
Garrison Davis
e426ec414a Add back ability to make on-demand instances
Also addressed the couple TODOs I left behind in the terraform.

(cherry picked from commit 4d75eda557)
2022-12-12 09:01:20 -08:00
Garrison Davis
f7a7a8a0c0 Make tflint and terraform fmt changes
(cherry picked from commit d028b6bc4b)
2022-12-12 09:01:20 -08:00
Garrison Davis
bc01e4c55c Make spot instance selection dynamic
The idea behind this is to give AWS more information about what
instances we can let it actually instantitate, rather than have it be
one fixed instance type.

e.g., in this case, we are okay with any Graviton instance with at least
2 vCPU and 8 GiB memory.

The easist way to do that is to instead use a launch template, with
ec2_fleets or spot fleets.

I took out the part where we even support on-demand instances. This can
be readded later if it is necessary.

(cherry picked from commit 3bfb65eb58)
2022-12-12 09:01:20 -08:00
Travis Turner
202a296131 rename shard partition field (#2302)
* Rename dax.Shard to dax.VersionedShard

* Rename dax.Partition to dax.VersionedPartition

* Rename dax.FieldVersion to dax.VersionedField

* Rename go files to a standard

(cherry picked from commit 49d0e0fbc8)
2022-12-12 09:01:20 -08:00
Matthew Jaffee
10026d0a90 run just the batch tests for the batch tests
(cherry picked from commit 12dd3c5996)
2022-12-12 09:01:20 -08:00
Seebs
490a2c57b0 stop uploading test results to sonarcloud, stop telling it we did
This gets complicated. For coverage output, sonarcloud supports wildcards.
For test output, it doesn't. So we weren't getting meaningful results,
just weird error messages. I fixed that, and got thousands of lines of
other error messages because it wasn't finding the test source files.
That looked like this:

	WARN: Failed to find test file for package
	github.com/molecula/featurebase/v3 and test
	TestTranslation_Primary

But we don't actually need the test reports sent to SonarCloud, because
"which parts of your test suite are being run" is sort of inherently
"basically all of them" with go test. So rather than continuing to do
that, we drop it.

Since we're dropping that, we don't need the JSON output from go test
anymore, so we drop that too, and the tee commands, and the "artifacts"
from the tee commands, and now our test output is human-readable and
slightly faster.

We also bump SonarCloud to 4.7.

We also fix the tests to use GOVERSION sometimes and GOFUTURE other
times, and bump from 1.19.2 to 1.19.3.

Also a couple of minor cleanup (adding explanatory comments,
combining adjacent grep commands, etc.)

(cherry picked from commit da4fb4ab4e)
2022-12-12 09:01:20 -08:00
Seebs
575f2c04a5 drop invalid UTF8 encoding from encoding tests
Testing unicode is great, but we appear to have had a couple
of cases where we were using strings that weren't valid UTF8.

Weirdly, other instances of these strings work -- I think because
they're in raw quotes (backticks) rather than strings. Anyway,
this is what SonarCloud fusses about.

(cherry picked from commit ab543adbe3)
2022-12-12 09:01:20 -08:00
Travis
04aa8b18fc Add DAX - full list of squashed commits below
In this commit, the Directive is mocked; it doesn't actually reach out
to a controller.

Limits key translation to only those partitions (per index) specified in
the Directive. Attempting to create or find a key (or ID) for a
partition which is not handled by this node will result in an error;
translation requests are no longer forwarded to other nodes.

Limits import into only those shards specified, per index, by the
Directive. Attempting to import into a shard which is not handled by
this node will result in an error.

Stub out /directive endpoint

The `applyDirective()` method still needs to be implemented.

Update mds references to use the new /mds/types structure

In mds, we moved the shared types to mds/types. FeatureBase needs to
reference those instead.

This also bumps the mds version in go.mod.

Implement the Add/Remove Index part of Holder.ApplyDirective()

This adds functionality to `Holder.ApplyDirective()` which adds or
removes indexes (tables) based on those provided in the Directive. Still
to be implemented here: shards and partitions.

WIP: remove client from Batch

Move Batch into its own package: batch

Also, in order to avoid import loops, this introduces packages:
/batch/types
/client/types

Reorganize the Importer-related code

Moved the Importer interface to package: batch
Move the "pilosa client" implementation of the Importer interface to
package: client

Modify batch.NewBatch to take an Importer (not client)

This commit modifies the batch.NewBatch() function to use a functinal
option on Batch to inject an Importer into the Batch. Prior to this,
NewBatch() took a pointer to a client, which was a little too
restrictive. Now, MDS can implement an Importer which uses information
from MDS to determine to which node(s) the import calls should be directed.

Add client.SetAuthToken() method to satisfy SchemaManager interface

Update ApplyDirective logic to include fields.

This needs more work, but it was enough to get a basic test passing.

Move Transaction type into /types package.

Add interface check on batch.Importer no-op implementation

Updated ApplyDirective to create all currently support Field types

There are still the following TODOs:
- [ ] impolement field options (ex: decimal scale, int min/max, etc).
- [ ] `time` fields

Added support for Decimal.Scale in ApplyDirective

Update mds dependency

Add /health endpoint

Update to use dax (dax/mds) instead of mds.

After moving the mds repository into the dax repository as a
sub-package, this commit changes everything in FeatureBase to use the
dax repo instead of the now abandoned mds repo.

Introduce and implment the WriteLogger interfaces.

This adds both a `WriteLogReader` and `WriteLogWriter` interface. They
are both implemented by the implementation: `fileWriteLogger`. The
`fileWriteLogger` uses the dax/writelogger API to append log messages to
files on disk.

Add WriteLogWriter.ImportRoaring method to interface

This commit adds the `ImportRoaring` method to the `WriteLogWriter`
interface. Still to implement are the `Import` and `ImportValue`
methods.

Reorganize the ApplyDirective code

The primary goal was to cache the incoming Directive on the Holder prior
to applying all of the changes in the directive (i.e. loading data from
the WriteLogger) because applying those changes often validated against
the accepted state of the node.

Implement all of the WriteLogger read/write methods

Implement the HTTP WriteLogger implementation

WIP: Introduce shard.Version. Implement snapshotter.

Add HTTP Snapshotter implementation

This also recofigures server to use the HTTPSnapshotter instead of the
FileSnapshotter.

Implement snapshotter: TableKeys

Implement snapshotter: FieldKeys

Dependency dance

last of the dependency dance

Add support for prototype

This adds the Makefile targets to build the docker container and push it
to ECR.

SQL3 changes which break with dax changes

Missed TODO: implement FieldVersion version to WriteLogger

Address bug causing missing TranslateStores to error

Originally, we tried to limit the TranslateStores which get allocated to
only those for which the node is responsible. This works when adding a
new table. But if a table already exists, there's no logic to start
missing TranslateStores.

This reverts back to the old FeatureBase logic which brutishly allocates
a TranslateStore for every partition, even if one is not needed.

We need to address this by allowing the ApplyDirective logic to
initialize TranslateStores when they don't yet exist.

Move the ImportRoaringShardRequest type to the types package

Since the ImportRoaringShardRequest object is part of the Importer
interface, we need to move it to a non-root (i.e. pilosa) package. All
the other interface types are either concrete types or part of a
sub-package (such as roaring). We do this to prevent an implementer of
the interface from having to import the entire pilosa package and risk
circular imports.

buncha changes to support latest dax stuff

Move dax related types to /dax sub-package

This commit moves all the common "dax" types into the /dax sub-package.
The idea is to ensure that featurebase does not import dax at all.
It's ok if dax imports featurebase.
In the future, we might need to split the dax sub-package (common data
types used by muliple molecula data-plan services) into it's own repo.

Add type: dax.Schema

This isn't currently being used; I started to use is as a replacement
for pilosa_client.Schema, but then deferred that. But we'll need to do
it eventually, so it doesn't hurt to have this type in place.

Export RowIDs.Merge() method for use in orchestrator.

Add CreateSQL method to dax.Table type

The CreateSQL() method will return the "CREATE TABLE" statement required
to create the dax.Table.

Comment out confusing writelogger log message.

We need to revisit this, but for now, this log message is confusing.

Also, rename daxSharder to versionStore.

Remove hard-coded AWS account

Implement more FieldOptions such as Epoch

Some of the FieldOption logic was stubbed out in the dax package. This
commit fills that out more; specifically, it adds the
dax.Field.Options.Epoch parameter.

export stuff needed for TopK in orchestrator

export ValCount stuff to implement Percentile in orchestrator

export more stuff to support less code in orchestrator, shared objs

Port dax repo over to featurebase/dax (run all as sub-services)

This commit does ALOT. Sorry.
It introduces a `featurebase dax` sub-command which can be configured to
run the various dax services as sub-services within the same process, or
individually as the lone service in process.

It also changes all the URL paths to be prefixed with the service name.
So for example, instead of calling localhost:8080/status, you would now
call localhost:8080/featurebase/status.

Also, note that all services provide a /health endpoint to confirm they
are running in process.

Clean up integration tests. Remove PILOSA_ config prefix.

Remove duplicate clients (mistake from porting dax to featurebase)

Rename sub-service "featurebase" to "computer"

In the places where we have hard-coded the sub-service name into a URI
path, I've tried to tag the line with a comment containing:
`// #SERVICEPATHPREFIX`

Update copilot manifest files to reference "computer"

Port dax/README.md from dax repository

Separate (toml) Queryer Config from Injections

We needed to separate the toml config from the configuration required to
inject sub-services into the Queryer. I'm not sure this is the best
solution, but it's *a* solution. So here we are.

Clean up (i.e. remove) the queryer "implementations" package

Remove old test file

Run WriteLogger and Snapshotter as local sub-services.

Prior to this commit, the writelogger and snapshotter services only
worked when run as separate services. This allows them to be run in the
same process as all the other dax services.

There is still some naming issues that we should address, but it's
functional for now.

Clean up (i.e. organize) the intra-service interfaces.

Implement alpha Director for local messages from MDS to Computer

Prior to this commit, messages from MDS to the computer service were
still going over http. This commit introduces an interface
implementation which registers the local computer command, and use that
command's API to directly reference methods used by the Director.

Clean up a few more interface names

Add Queryer OpenAPI document.

Update copilot manifests to reflect latest changes

Add OpenAPI documents for WriteLogger and Snapshotter

Add OpenAPI document for MDS service

Add OpenAPI document for Computer service

Consolidate errors to use fb/errors package.

This commit is a first pass at trying to ensure that all of the DAX code
uses:
"github.com/molecula/featurebase/v3/errors"

This package is a wrapper for "github.com/pkg/errors", so going forward
we want to avoid importing that package.

The only method which isn't backward-compatible is `New()`; the
New() method in the featurebase/errors package takes an errors.Code. If
this becomes a problem, we could change this by reverting New() and then
introducing something like NewCoded(). But for now I think it might
actually discourage someone from just creating a New() error without
thinking about how it should be coded.

Introduce VersionStore interface

Move the existing VersionStore code to the `inmem` package as the
in-memory implementation of the new dax.VersionStore interface.

Introduce NodeService interface

With this, the Controller can maintain a registry of nodes by using this
NodeService interface as opposed to an in-memory map of nodes on the
Controller struct.

This also adds an inmem implementation of the NodeService interface.

Introduce controller.Balancer interface

This moves the existing balancer package to controller/naive package.
The idea is to allow us to add a different Balancer implementation in
the future.

Introduce DirectiveVersion interface

This commit also includes *A LOT* of refactoring to use dax.Worker and
dax.Job types everywhere instead of strings.

Introduce Schemar interface

The previous `Schemar` struct was moved to the `schemar/inmem` package,
and `Schemar` is now an interface implemented by that inmem package.

Remove unused type `nUnit`

Add boltdb implementation of VersionStore interface.

This removed the previous sqlite implementation; we decided not to use
sqlite for now (as a basic, local disk implementation) because it
requires CGO.

--------------------------------------------
No longer applicable:

Add sqlite implementation of VersionStore interface.

This commit implements the VersionStore interface using sqlite. Sqlite
requires CGO, so this may not be something we want to include, but it's
implemented here to get a feel for how an external implementation might
be used; the next step will be to determine how the user configured
FeatureBase to run using sqlite as a backing store for services like
MDS.

Add boltdb implementation of NodeService and DirectiveVersion interfaces.

Add boltdb implementation of naive Balancer interfaces.

This includes the two interfaces defined in `naive/balancer.go`:
- WorkerJobService
- FreeJobService

Add boltdb implementation of Schemar interface.

clean up a linter issue

Thread context.Context through all the interfaces.

Some of the interface implementations are going to use context, so we
need to make that part of the interface. The boltdb implementations, for
example, take a context. This is probably so we can do things like
cancel or timeout operations.

Update interfaces to return error; remove `panic(err)` everywhere.

Down-rev grpc version to 1.38.0

Later versions (after 1.42.0?) cause MustRunCluster.Close() in tests to
deadlock.

This commit also adds an `isComputeNode` feature flag around some of the
write log and shard/partition check functionality so that it doesn't run
under normal conditions (this is excercised by running the sql3 tests
for example).

Add MDS_Persistence test to cover meta data persistence

This adds a basic test which configures the MDS container to use boltdb
as its persistence storage, saved on a docker volume. Then, the mds
container is stopped/replaced, and we confirm that the data stored on
the volume is availble to the new MDS container.

Fix a few things after rebase with sql-experiment branch

The lastest version of sql-experiment contains a fairly significan
refactor of the way query iteration works. This commit adjusts for those
changes.

pull dax IDK changes in to FB IDK (#2177)

* pull dax IDK changes in to FB IDK

* Move docker-related IDK build stuff to featurebase root

Building the docker image required the root level go.mod and vendor
directory. This change moves the make targets to the root level
Makefile, and the Dockerfiles now copy the root level vendor directory
(and everything else in the root for that matter).

* Fix batch- and client-related tests

* InitializePoller on MDS restart/replacement

Prior to this change, if MDS was restarted, its internal poller (which
maintains an in-memory list of nodes to poll) is empty. This is bad,
because it doesn't know about nodes that it should be polling.

This change fixes that. Upon MDS startup, it intializes the poller with
the list of nodes that MDS keeps in persistent storage (currently:
boltdb).

* Add EFS volume to MDS Copilot manifest

This allows us to use MDS's persistent storage (via boltdb) in the
Copilot demo by saving metadata in a boltdb file on EFS.

* Thread logger.Logger through all dax components

* Revert some of the breaking changes from DAX development.

When we first started prototyping DAX, we made changes to the
featurebase core code which would have broken the existing featurebase
functionality. This commit reverts some of those changes. Anywhere that
we need to modify core featurebase functionilty, we put it behind some
kind of feature flag. This flag is typically determined by whether the
running node is a "compute" node (i.e. DAX.COMPUTER.RUN = true).

Co-authored-by: Travis Turner <travis@molecula.com>

add packaging for DAX

need cgo for datagen build

bind to 0.0.0.0, pass GOOS and GOARCH explicitly

not sure if the explicit GOOS/GOARCH is actually necessary...

Get INSERT INTO (aka ingest) working through SQL3

This commit does a few things which I'll try do describe here.

- Introduces a Qctx interface. The existing Qcx is an implementation of
  this interface, and can be used exactly how it has been. But this
  allows us to abstract away the notion of Qcx in the Queryer (which is
  handling SQL3) until we're ready to address that. As an example, the
  Qcx has a notion of a featurebase Holder, but that doesn't make sense
  when we're at the Queryer layer. For now, the Qctx used in the Queryer
  is a no-op.

- Adds a ComputeAPI interface implementation for the Queryer. This is
  effectively the Import() and ImportValues() methods used for ingest.
  The logic here handles the incoming ImportRequest by first doing any
  necessary column and row translation for the entire request, then it
  splits the records by shard, and generates a new ImportRequest per
  shard with only the shard-appropriate records.

- Changes the mds.Importer to take an MDS interface implementation
  (which can be an mds client) instead of an mdsAddress. This allows us
  to use a localy MDS implementation rather than assuming we need a
  client to make calls over a network.

Add queryer.Importer interface to handle ingest via SQL (#2203)

* Add queryer.Importer interface to handle ingest via SQL

This is meant to support ingest through SQL when the queryer and the
compute services are running in the same process, or when they are on
seperate processes and need to talk via http client.

* remove datagen from RPM

was originally added as a convenience to generate test data, but is
unused and annoying because datagen doesn't easily cross-compile due
to cgo

* add marshalUnmarshal to controller to avoid passing pointers

passing pointers across API boundaries can cause unpredictable things
in local vs remote configurations.

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>

"fix" a few issues with wrong default partition numbers

these still need to be properly fixed and actually get the correct
data from MDS

go mod tidy

Introduce TableQualifier (OrganizationID/DatabaseID) (#2220)

* add check in ApplyDirective that version is increasing

fix TestAPIDirective to make version always increasing

* fix docker image build and break out dax test in CI

We have to run the DAX integration tests separately as they call out
to Docker, and so it isn't easy to run them in a Docker container as
the other tests do. So we run them directly on the CI runner which has
Docker and Go installed.

We also explicitly exclude these tests from running during the other
tests.

Also my editor was automatically reformatting some comments badly
which is why I added the "data" thing in those two places

* add timeout to poller

* give Poller a default Logger

apparently we can NPE sometimes, seen in CI: https://gitlab.com/molecula/featurebase/-/jobs/3028286364

* bunch of testing fixes, mostly IDK/DAX related

make MDS error if sendDirectives errors, don't just
log. sendDirectives can error if computer nodes disagree about the
validity of a schema (for example), in which case it might need to get
deleted and user notified somehow. very messy, needs more thought.

re-introduce old env prefix to maintain compatibility with master
branch

make self-contained dax container for IDK testing

build IDK images from source (now that all the source is available
since it's in the same repo)

catch errors in DoExtractQuery in idktest.go

fix IDK bug where prefix path was hardcoded in all cases rather than
only when useMDS was true

fix TestBatchTargetMDS... needed to add field options and catch error
when creating table. also needed an _id field

* fix env prefix in tests

* WIP getting tests to pass, wanna see CI

* don't error if we get a zero version directive and we don't have a

directive yet

* cleanup debugging junk

* "fix" future.rename thing, run IDK tests

* Introduce TableQualifier (OrganizationID/DatabaseID)

This commit introduces a lot of new types (in dax/table.go) related to
TableQualifer (which is made up of OrganizationID and DatabaseID), as
well as things like TableID and TableKey.

For the most part, we try to thread a QualifiedTableID through the
entirety of DAX. There are some places (for example in the Balancers,
which are just aware of string keys) which use a string TableKey
(tbl__org__db__tableid).

* Remove some debugging comments

* Add Org/DB support to CLI.

This commit adds support for special commands:

SET
SET ORG acme
SET DB db1
USE db1

* remove ".pulled" from IDK Makefile

I don't think we need it any more as most things can be built
locally. I think it was only there to refresh the FeatureBase images
that were tagged as master, but we don't need to do that any more.

* Change DAX json tags to kebab-case (i.e. hyphenated)

This commit also renames some struct arguments to more accurately
reflect their type: for example, renaming `Table` to `TableKey` when the
type is TableKey.

* Return DAX TableName in SHOW TABLES (instead of Index.Name)

There are cases where SchemaAPI is used to return DAX friendly table
names (as opposed to featurebase index names, which are DAX TableKey).

This is an attempt to do that. With that said, it's not ideal because
anything could call those API methods and expect the other type.

* Fix a bug which wasn't completely dropping a table.

When using boltdb as a backend, DROP TABLE wasn't removing the
reverse-lookup key for the table in boltdb.

* Remove idk/testenv/certs which got accidentally committed.

also update .gitignore to include those.

* Fix IDK ingest tests to be TableQualifier aware.

* Add example Table types to dax/table.com godoc.

* ignore idk.Main fields for flags, upgrade commandeer

* go mod tidy

* Fix DAX integration tests: ingester using wrong ENV VARs

We change from ORGANIZATION_ID to ORG_ID
and from DATABASE_ID to DB_ID

* Clarify things around idk (docker) tests

* Stop running TestKafkaSourceIntegration with t.Parallel()

This test can't be run in parallel as it's currently written. Doing so
allows for interleaving of messages to the same kafka topic between
tests.

I didn't attempt to modify the test so it could be run in parallel. That
could be done, but left for someone more ambitious.

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>

Require Directive.Version be a non-zero value. (#2227)

Because the directive cached on the holder is not a pointer, its default
version is 0. In order to avoid having to compare against that, we just
require that Directive.Version start at 1.

General, non-invasive code cleanup and comment adjustment.

Move ImportRoaringShardRequest out of the types package

Early on in the DAX development, I moved ImportRoaringShardRequest into
a types package. There must have been some import loop going on, but
since that is not longer the case, it's safe to move this back into the
core featurebase (er... pilosa) package.

Move Transaction struct back into the pilosa package (from types)

Revert some name changes (cli -> client)

Add DAX Handler CloseTimeout

This was implemented in htt_handler.go, but it had been commented out in
the DAX handler. This just uncomments that and finishes the
implementation.

Remove Qcx from queryer.Importer interface

This sets us up to revert the Qctx interface that was initially
introduced to allow us to abstract away the need for a Qcx when calling
the ComputeAPI from a remote service (i.e. the queryer).

Add some go-doc comments and remove unused code.

Move SchemaManager setup from datagen to idk.Main (#2233)

The set for idk.SchemaManager (for dax implementations) was previously
in datagen. This may have been because of some import loop problem
during development, but that's no longer an issue.

The setup for this should be in idk.Main so anything using that can
leverage the MDS-specific SchemaManager setup.

Fix issues around nil TxFactory

First, don't return a nil. Rather return a new *TxFactory (with no
holder).

Second, don't call `f.holder` in the testhook outside of checking if
`f.holder` is nil.

Wrap all bare errors

Make service prefixes constants

Instead of having `"computer"` throughout the code, use instead a
constant: `dax.ServicePrefixComputer`.

MDS skip errors when sending empty directives

also add in the docker-login and ecr-push changes for serverless DAX

Fix the logic in Directive.IsEmpty() (#2236)

Update the cached value for Index.translatePartitions

In the case where a node already knows about an index, but its
assignment of partitions for that index changes (for example, when
another node goes down and the node in question is now responsible for
more partitions than it previously was), then we need to update the
cached value of Index.translatePartitions because that's used in
translation checks.

minor fixes for IDK-related bugs

WIP: tokenize CLI to access cloud

FB CLI cloud support with automatic token refresh

Also adds support for a GET command which allows making HTTP GET
queries to cloud CP which can be handy for debugging stuff. E.g. GET /v2/databases

buncha little fixes working on writelogger stuff

fix writelogger/snapshotter setup bugs

implement writelogging for importRoaringShard

add debug endpoint to MDS

use shard transactional endpoint in MDS datagen

add debugging to API related to writelogger

revert handleroption change

clean up big PR

remove "GET" command from CLI for making arbitrary HTTP request to
cloud control plane (was a messy hack and not that useful)

remove json tags from FB objects where we had to duplicate the object
elsewhere due to import loops and weren't actually json encoding it

unexport handlerOption which was exported to try to avoid doing
certain things if we're in DAX mode, but I didn't end up merging that code.

remove (hopefully) unecessary extra call to api.indexField

fix some formatting, unexport some vars, godoc, etc

oops, fix build failure

Update FeatureBase CLI to support a standard deployment

The standard deployment uses a different endpoint and request payload.
This commit tries to detect is the standard deployment is being used,
and if so, it uses a standard-specific FBQueryer.

It also modifies the auto-detection logic to try standard featurebase
and dax ports in the case where a port was not provided.

MDS API refactor (#2259)

* MDS API refactor

table IDs are exposed but only created server side

also cleaned up dax Makefile

* clean up review feedback

Co-authored-by: Travis Turner <travis@pilosa.com>

* remove TablesByName

* rip out inmem implementations and use boltdb everywhere

* remove inmem balancer, create bolt tempfile by default on startup

* WIP on snapshot table impl and test

* Minor comment and code layout adjustments.

This commit also adds the `Equals` method to `QualifiedTableID` for
equality comparisons. It's no longer safe to compare struct (two structs
might still be equal even if one of the structs doesn't have a `Name`
value.

* Use a unique docker network for each dax test

Ocassionally we would see some test failures due to a network already
existing. This shouldn't happen, but to avoid that, this commit
generates a unique name for each sub test (which gets deleted at the end
of every test).

* Fix one instance of NewQualifiedTableID losing Name

We should probably check the other instances and see if Name is getting
lost.

* simplify unique network stuff and fix api directive tests

* Remove TableIDRequest and TableIDResponse types for /table-id (#2267)

For the mds/table-id http requests, just use dax.QualifiedTableID as
both the request and response types.

* remove lattice from dax, no error on node re-reg, dax docker-compose

* various updates

* WIP: mds-refactor branch review

* no-op on SnapshotTableKeys if table is not keyed

* Makefile helpers

* add doWeCare so controller doesn't fail unnecessarily

* clean up table creation (#2272)

* Strip underscores from TableID stub name

* fix boltdb versionstore tests: generate unique, sorted tables

* fix controller test related to reregistering a node

* JobSet -> generic Set

Co-authored-by: Travis Turner <travis@pilosa.com>
Co-authored-by: Travis Turner <travis@molecula.com>

Cleanup after rebase on master

The latest rebase on master entailed all the client/batch changes as
well as some of the qcx refactoring. It made for a hairy rebase. This
commit fixes some of the tests that were failing after that rebase.

Fix batch/client import loop missed during rebase (#2280)

It's not surprising that `batch` can't import `client`. It was doing
that here (importing an error type from the `client` package). What is
surprising is that it's okay for `batch_test.go` to import `client` even
though `batch_test.go` is an internal test and therefore part of the
`batch` package.

different boltDB's for schemar/controller, explicit balancers

nice helpers for dax docker-compose, make build really fast

build FB binary outside of docker, then create Docker image with its
working dir in an empty subdirectory so it doesn't send a GB of
context to the daemon.

error on unassigned jobs and use client with timeout

fix CR feedback

deregister batch of nodes

also make removal faster via director dial timeout

implement WorkersForJobPrefix so orchestrator doesn't make up shards

also fix some godocs and remove unused method

Run sub-tasks of a Directive concurrently in a worker pool. (#2275)

* Run sub-tasks of a Directive concurrently in a worker pool.

This allows the compute node to concurrently load shapshot and writelog
data concurrently, instead of one keyset/partition/shard at a time.

It introduces a config parameter called `DirectiveWorkerPoolSize`.

* code review cleanup

* Use unique container names in DAX integration tests

We were seeing "container already exists" errors in CI, so just to be
safe, this commit constructs a unique container name for every container
in the DAX integration test run.

Stub in SystemAPI to Queryer (note: will not work if used)

This just makes is so that dax can compile. Actually implementing
system-table functionality for dax will take some planning.

Tlt/dax merge prep (#2282)

* Remove copilot directory

* Remove Dockerfile-datagen-long

* Remove orphaned RegisterNodeRequest

This type is not defined in the dax/mds/http package.

* implement TIMEQUANTUM and TTL in Table.Field type

* Remove the "service" misdirection in queryer/writelogger/snapshotter.

We had originally used an additional layer, er.. package, for a "service".
The main distinction was that the Config differed in that it was
internal, unlike the Config that we need to provide for the top-level
server config (i.e. toml). Having that additional layer just to support
a different Config seemed premature at best. So I'm removing it.

* Remove dax docker containers no longer used in tests

Since we run everything as "featurebase", we don't have multiple
container types anymore.

* Some minor comment updates

* Remove nfpm stuff related to dax

* Fix linter issues

Fix "duplicate" issues raised by sonarcloud.

run docker components of dax integration tests with coverage

trying to get dax integration coverage

add coverate volume mounts throughout dax integration tests

add a lock, tweak dax Makefile, remote flag on query handler

remove some unused code

convert batch tests to use clustertests to get coverage

maybe fix clustertests

more authclustertests fixes, test is failing locally

but also seems to have been silently failing in CI prior to these
changes... let's see if it's still silent

fix some lint to kick CI

just re-running the job wasn't working... strange behavior

remove RetryLogic test and pipe which don't work

RetryLogic test removed due to etcd changes. Seebs thinks we shouldn't
test this here.

Pipe was being ignored since we're no longer using "bash -c" to
execute the command. If we need to generate that output file we'll
either have to reintroduce bash -c and set -o pipefail so that it
actually fails properly, or figure out some other solution.

shooting into the dark...

first cut at bulk node registration

remove unused stuff from batch tests, set coverpkg to ../...

batch registration timeout and fix tests

disable most tests and don't run fb background batch test

debuggin!!!!!!!!!

and then he tried this....

Implement importer (for INSERT INTO) in the Queryer

Prior to this, we we passing a nil value in for the importer to the
planner.NewExecutionPlanner in the Queryer. This meant that INSERT INTO
statements didn't work. Now they should.

It uses the importer that we build for IDK in /idk/mds/importer.go, and
wrapps that with a type that can determine if the provided string
"index" is of the form indexName or TableKey.

turn off debug mode, fix log saving

Run sql3 test definitions in a dax integration test

There are currently 22 tests which are not passing. They are skipped in
the "skips" slice.

WIP, not working, pql queries to tests

Add TableQualifier to PQL query logic in the Queryer

Add more PQL tests to the keyed table

Allow instant node registration if registration-batch-timeout=0

When running dax services in process, we don't want to wait 3s for the
compute node to register; we know it's there because it's in the same
process.

Fixes related to IncludesColumn PQL test.

Tests for ConstRow and FieldValue

cleanup

add UnionRows and Options, better error reporting on bad queries

delete unused schemar client.go, clean up unused in batch test CI

move test timeouts into more reasonable territory

apparently this had already been done, but got merge-stommped at some point

move dax bolt test helpers into dax package

Add computer CheckIn routine (#2296)

* Add computer CheckIn routine

This adds a background routine which sends a "check-in" request to MDS
every <interval>. This is to address the case where the poller has
removed a computer node from the node list (due to a network fault, for
example), but the node is still healthy and becomes available again. In
that case, the node needs to "check-in" to tell MDS it is still there.
MDS will likely send the node a new directive with Method=reset telling
the node to delete all of its data an apply the latest directive.

* Don't send directives to Deregistered (i.e. removed) nodes

We have an issue where we're locking on sendDirective in the
controller, and when the node is unavailable, the send hangs and never
releases the lock. This is a temporary fix for that until we address the
real problem.

Fix .gitlab-ci.yml after rebase

fix some indentation shenanigans

(cherry picked from commit 20a8b5713a)
2022-12-12 09:01:20 -08:00
Bruce Baranowski
06a63021b1 Re-allowed concurrency for molecula-consumer-csv when not using '--auto-generate' (#2294)
Concurrency was previously fully disabled due to duplication when using '--auto-generate' but testing has shown that it works correctly when not using that flag. Added the required check and updated help text

(cherry picked from commit ba70bee875)
2022-12-12 09:01:20 -08:00
Seebs
c99faa1793 bump timeout on overlapping write requests test
At 50ms, we see sporadic failures in CI. So much for "this should
only need a couple milliseconds". Bumped timeout to avoid that.

The challenge here is that we have some tests which *want* to hit
the timeout to confirm that we aren't allowing things we shouldn't.
But we don't want the test to hang forever. But we want to be sure
it is actually stuck and not just being slow...

(cherry picked from commit f1a68f8a82)
2022-12-12 09:01:20 -08:00
Fletcher Haynes
2709973b08 Fixed import in idk ingest 2022-11-17 15:56:14 -08:00
Fletcher Haynes
8e03df719d Fixed a few more conflicts around imports with the latest sync 2022-11-17 10:00:53 -08:00
Fletcher Haynes
45e405b980 Fixed some import issues resulting from syncing the private repo 2022-11-17 08:58:22 -08:00
pokeeffe-molecula
e14cde7341 SQL BULK INSERT (fb-1749) (#2291)
SQL BULK INSERT

This change is to support a BULK INSERT/REPLACE statement that adds the ability to 1) take its input from a file, url or in-line blob 2) to map from the input source to the target columns
3) to transform data (using sql expressions) before inserting
4) support csv and ndjson formats

* improving test coverage

* increase test coverage again

* refactoring for handling transformation with types other than id and int

(cherry picked from commit 8f660a5033)
2022-11-15 11:33:38 -08:00
Travis Turner
53170cef64 Move SQL3 test definitions into sql3/test/defs package (#2289)
This so other packages can import and use them in their own tests.

(cherry picked from commit eec278893a)
2022-11-15 11:33:35 -08:00
Julio Martinez
b3a408aa4e Packaging improvements to improve mcloud updates (#2288)
* Update package scripts so they restart services based on the operation (update vs install)

Co-authored-by: Julio Martinez <julio.martinez@logicmonitor.com>
(cherry picked from commit e25e395bab)
2022-11-15 11:33:12 -08:00
Seebs
ec6f256df9 rename protobuf interface
For unrelated reasons, we renamed the protobuf interface from
package "pilosa" to package "proto". This means our GRPC endpoints
need to live under "proto.Pilosa" instead of "pilosa.Pilosa". This
means lattice needs to be configured the same way.

(cherry picked from commit 3a8d08fed5)
2022-11-15 11:33:12 -08:00
pokeeffe-molecula
eb842274ec fb-1744 implement system tables (#2276)
* implement system tables that contain internal state information from FeatureBase

* review feedback

* review feedback

* removed sys prefixes

(cherry picked from commit 45067b4e32)
2022-11-15 11:33:12 -08:00
tgruben
dcdc99db25 enable staticcheck in ci; remove dead code (#2281)
(cherry picked from commit 0d6a92aeaf)
2022-11-15 11:33:12 -08:00
tgruben
751b7a74fe staticcheck fixes (#2278)
(cherry picked from commit 0aa5efcc51)
2022-11-15 11:33:10 -08:00
Garrison Davis
13a32409f3 Fix server.GetIndexes userInfo logic
userInfo at the relevant line can be nil here. We check later if the
userInfo != nil (and assure it passes authn/authz) or if userInfo == nil
then we return all the indexes we can find.

(cherry picked from commit 407d52baa0)
2022-11-15 11:32:03 -08:00
Garrison Davis
ab2b48da0d Stop using string keys in contexts
This fixes the OriginalIP and RequestUserID in the main featurebase
package, and the Access and Refresh tokens, the UserInfo, and the
[]string of Indexes passed with context.Context(s) in the authn package.

An empty struct was used for all of these keys (and relevant helper
functions we added) to avoid allocations where possible while still
using the context functionality.

Some of the logic in the server.GetIndexes function was fixed.

(cherry picked from commit 0f5a56c958)
2022-11-15 11:32:03 -08:00
Bruce Baranowski
202501f7bf Makefile Cleanup
A cleanup pass to remove unused or broken makefile commands, this will help make the Makefile more clear and useful.
Removed unused makefile entries:
- release-build
- test-release-build
- check-clean
- release
- release-sans-ui
- plg
- install-bench
- generate-stringer
- pilosa-keydump
- pilosa-chk
- pilosa-fsck
- docker-test
- topt
- topt-race
- gometalinter
- install-stringer
- install-protoc-gen-go
- install-gometalinter

(cherry picked from commit 6800e52a39)
2022-11-15 11:32:03 -08:00
Seebs
7db504e5ee finish removing traces of ingest API
A couple of helper functions and types were left over from
the ingest API. Thanks, staticcheck!

(cherry picked from commit 0c904b3fae)
2022-11-15 11:32:03 -08:00
Seebs
10edb62b83 initial implementation of RBF backend
This provides us with most of the existing Tx interface, split
across QueryRead and QueryWrite. The functions not included here
are the ones that are used *only* for anti-entropy (ForEach
and ForEachRange).

We add additional testing to verify that TxStores are getting
closed correctly, to go with cleaning up the test directories they're
made in.

We also introduce some test wrappers that can automatically
fail tests on error, so tests don't need to be full of error
checks.

Also, now that I'm starting to think more about the flow of
writing tests using QueryScope, we add the missing "full
database" scope option, and make the Add methods return
their operand so (1) you can chain them, (2) you can use
the AddIndex(...) inline in a NewWriteQueryContext.

Also addressed a plausible performance concern in shardList,
and some comments that were stale or incorrect.

The test coverage here is skimpy on the actual RBF-calling
functions because those are trivial. We do, however, significantly
expand coverage in the random write requests, which are now
a mix of random writes and random reads, and add test cases
that at least hit a lot of the error checks once.

The Error() method is changed to be like (testing.T).Error(),
taking ...interface{} and using fmt.Sprint on them.

There's also some minor tweaks such as making the visualizations
more consistent, testing visualization generation on two kinds
of keysplitter, and so on.

(cherry picked from commit 7b434cd11c)
2022-11-15 11:32:03 -08:00
Seebs
c02a4b5e47 use Fatalf instead of Fatal(Sprintf)
(cherry picked from commit b4eb1b8bdc)
2022-11-15 11:31:41 -08:00
Seebs
a508a15f3b drop unused CreateDirIfNotExist function
I was wondering why this is exported, and the answer is, if it
weren't exported, staticcheck would have reported that it was unused,
which it is. We don't need a wrapper on os.MkdirAll that we never
use.

(cherry picked from commit e9a40cdc35)
2022-11-15 11:31:13 -08:00
Seebs
7d1fde7438 drop anti-entropy feature, since it doesn't work
The anti-entropy feature has never actually worked. We've been
talking about removing it or replacing it for ages, but haven't
had a concrete motivation.

But the anti-entropy interface is the sole user of several components
of the Tx interface, and now that we're trying to replace that
interface, being able to drop those components has some appeal, so
let's remove the one thing that used them, in the hopes that this
will simplify life.

This also lets us drop ForEach and ForEachRange, which were
barely used at all. The one surviving usage (CSV export) can be
handled by using the container iterator we already have, and
making ContainerCallback exported so we can use it to just call
things for every bit.

(cherry picked from commit fff9ddc1f5)
2022-11-15 11:31:13 -08:00
Jacob Brinlee
bf00d028c7 updating topic/partition/offset order (#2250)
* updating order of topic/partition/offset in log message

(cherry picked from commit dd30168b1c)
2022-11-15 11:31:13 -08:00
Jacob Brinlee
d2a4ca3168 SUP-286 - update lattice config (#2273)
* comment out configs

(cherry picked from commit ca16e7f8fa)
2022-11-15 11:31:13 -08:00
pokeeffe-molecula
ae3910a22b Test expression eval for tuple values in inserts (fb-1555) (#2270)
refactored comparison, equality and arithmetic expr eval for decimal data types and added a test to cover expression eval for inserts

fixed failing test

(cherry picked from commit 193ef7cba1)
2022-11-15 11:31:13 -08:00
Seebs
bf00561caa Drop the ingest subpackage and related endpoints.
The internal/ingest and internal/schema endpoints were developed with
intent that they'd be the primary interface new users would work with,
because they were Easy To Use, and did not require any kind of setup,
the counterpoint being that ingest done this way had performance issues
because it ended up with huge amounts of JSON parsing to reformat
things into our native format. But this was understood to be the price
of providing a new-user-friendly JSON ingest experience.

A year later, we have no evidence that it's ever been used. We never
even moved it out of the `/internal` path. It's a lot of very complex
fiddly code and we don't seem to be using it, and at this point, our
anticipation is that if we really need something, we'll use CSV, which
we already have working, or something in the new SQL code. Either way,
we don't seem to be using this.

(cherry picked from commit 16ccbc461a)
2022-11-15 11:31:10 -08:00
Seebs
cb252a0e82 stop ignoring degraded/down states
We think etcd's tendency to mistakenly mark nodes down may have
been addressed. We can't find out without checking for it.

The exact pool of methods in methodsDegraded may have bitrotted
some; for instance, it didn't have PastQueries or PartitionNodes
in it, but it looks like it reasonably should.

We rework the Replica1/Replica2 server tests to reflect the
intended semantics again.

(cherry picked from commit 164dec1703)
2022-11-15 11:25:39 -08:00
Seebs
4467c18baa drop Starting cluster state
The special case of Starting allowed us to make sure every node in a
cluster waited for the whole cluster to come up, but caused problems
later if a node died and came back. We drop the Starting state for
clusters, treating a STARTING node as equivalent to an UNKNOWN (or
DOWN) node for purposes of cluster state, so clusters will go from
Down to Degraded to Normal as nodes come up. We now wait for the
Normal state during initial bringup. We would previously have accepted
Degraded, if you could reach it, for instance if a node came up and
then went down again before another node finished starting, but I'm
pretty sure that was unintentional.

This solves a problem where while a node was down, we'd accept
queries that we could handle in a degraded state, but then we'd
*stop* accepting them when the node started coming back up.

(cherry picked from commit 52d3329434)
2022-11-15 11:25:39 -08:00
tgruben
95287c2ee2 add flag to bypass space check (#2265)
(cherry picked from commit f987009406)
2022-11-15 11:25:39 -08:00
Travis Turner
bcb32addaf Batch insert via SQL (multiple tuples) (#2243)
* Formatting adjustments made during code review.

While reviewing the BULK INSERT logic (in order to decide how best to
approach "ingest via sql" in the cloud), I made a few formatting and
comment changes. I'm just adding them here as a separate commit so they
don't muddy up my actual work.

* Parser modifications to support mulitple tuples in INSERT INTO

This commit doesn't include all of the changes required in the
planner. Fow now, the planner is simply modified to continue supporting
a single tuple (the first tuple in the list).

* Update the planner to handle multiple INSERT INTO tuples

This is part 1. It's still using the existing logic which builds an
ImportRequest for every record (and every field!).

The next step will involve using a client.Batch to handle the records.

* Introduce client.Importer interface (used by client.Batch)

Instead of the Batch having a pointer to a client, this puts an
interface there instead (which the client implements). It also allows us
to inject a different importer (i.e. other than a featurebase.client)
into the Batch.

* Decouple batch from client

This commit pulls batch-specific code out of the client package and into
a new batch package. It introduces the batch.Importer interface, the
methods of which replace all the calls that batch was previously making
directly to client methods.

Finally, it contains two implementations of the batch.Importer
interface: one is a wrapper around client, and the other is a wrapper
around featurebase.API.

* Use docker (instead of MustRunCluster) for internal batch tests

Because the `batch` package tests are internal, using
test.MustRunCluster() resulted in an import loop (because it eventually
imports `server`, and we can't have that). So this commit replaces the
use of `test.MustRunCluster()` with docker. The setup is basically the
same as that used in the idk docker tests.

Here we also remove all client-side references to `UseIngestAPI`, which
is an experimental (json) ingest api. It's still suppored on the server,
but here we remove the external usage of it.

* cherry-pick fix

* Use batch.Import() for sql3 INSERT INTO statements

* Thread logger into sql3

* fix batch test

* Fix some shadowing complaint by linter

* Address some test issues related to stringsets

* Exclude batch integration tests from CI

* Address PR feedback

- Added description to batch.README
- Consolidated grep commands in .gitlab-ci.yml
- Removed some debugging comments
- Replaces some inadvertantly removed license headers

* Add batch package to gitlab CI

* Updated CI for batch package

Updated CI include path

Update gitlab ci

Update CI

Update CI

Trying new include path for ci

Updated gitlab ci include path

Made idk race job optional for sonarcloud upload

add testdata directory

remove testenv from dockercompose file

use GIT_STRATEGY clone in batch CI

add testdata volume to dockercompose

Co-authored-by: Fletcher Haynes <fletcher.haynes@generalassemb.ly>
(cherry picked from commit 00ef2380e5)
2022-11-15 11:25:36 -08:00
Seebs
0c94a53a73 initial implementation of QueryContext design
This is living in a subdirectory for now so we can have better
turnaround time on tests and not have to build everything else
along with it.

This covers the logic that we can have *without* actually using
databases or the filesystem in any way, just to provide a framework
that lets us validate the logic handling overlapping queries.

The overall purpose of this is to prevent deadlocks, by ensuring
that database locks are only taken when we have already proven
that they are available. In short, the QueryContext preregisters
its "scope" -- the set of things it may want to lock. The operation
of creating the QueryContext can block, but it blocks with no
database locks held. Once it is unblocked, the scope it has reported
is now considered unavailable, and no other QueryContext using any
overlapping scope can complete creation until this QueryContext
completes. While it's running, the QueryContext can't request write
access to anything outside its scope. Thus, once created, a
QueryContext can always proceed, without being blocked, until it's
done.

Note that this does not fully address multi-node behaviors;
once you have a QueryContext blocking things, you need to not
make queries to other nodes that could be blocked in turn by those
nodes. In short, no write queries to other nodes while holding a
write-type QueryContext on the local node, because if two nodes
do that to each other at once, they can both be blocked.

We believe RBF is currently designed such that read-only accesses
don't block progress on writes, so non-write access doesn't
create problems.

We also have some code to allow us to create dot-format output
from the components of this system, which is mostly intended to
be a debugging tool.

(cherry picked from commit e3d137f29c)
2022-11-15 11:22:17 -08:00
Stephanie Yang
76d62418d7 update molecula references to featurebase (#2262) 2022-11-15 11:16:08 -08:00
pokeeffe-molecula
93d8bb0bca added a test to cover the keyword replace as being synonymous with insert (#2261) 2022-11-15 11:16:01 -08:00
pokeeffe-molecula
b3753c3c5d tightened up is/is not null filter expressions (FB-1741) (#2260)
Covers tightening up handling filter expressions that contain is/is not null ops. These filters may have to be translated into PQL calls to be passed to the executor and even though sql3 language supports nullability for any data type, currently only BSI fields are nullable at the storage engine level (there is a ticket to add support for non-BSI field here FB-1689: IS SQL Argument returns incorrect error) so when these fields are used in filter conditions we need to handle BSI and non-BSI fields differently.
2022-11-15 11:14:35 -08:00
pokeeffe-molecula
957ba4086b fb-1729 Enriched Table Metadata (#2255)
enriched metadata for tables

added support for the concept of a table and field owners in metadata; mechanism to derive owner from http request metadata; metadata for table description
2022-11-15 11:14:25 -08:00
Seebs
b3ffab6928 don't obtain stack traces on rbf.Tx creation
We thought stack traces were mildly expensive. We were very wrong.
Due to a complicated issue in the Go runtime, simultaneous requests
for stack traces end up contending on a lock even when they're not
actually contending on any resources. I've filed a ticket in the
Go issue tracker for this:

	https://github.com/golang/go/issues/56400

In the mean time: Under some workloads, we were seeing 85% of all
CPU time go into the stack backtraces, of which 81% went into the
contention on those locks. But even if you take away the contention,
that leaves us with 4/19 of all CPU time in our code going into
building those stack backtraces. That's a lot of overhead for a
feature we virtually never use.

We might consider adding a backtrace functionality here, possibly
using `runtime.Callers` which is much lower overhead, and allows us
to generate a backtrace on demand (no argument values available,
but then, we never read those because they're unformatted hex
values), but I don't think it's actually very informative to know
what the stack traces were of the Tx; they don't necessarily reflect
the current state of any ongoing use of the Tx, so we can't necessarily
correlate them to goroutine stack dumps, and so on.
2022-11-15 11:14:14 -08:00
Pranitha-malae
1c6bc781f3 resolving bool null field ingestion error (#2254)
* resolving bool null field ingestion error

* testing issues

* adding null support for bools

* updating the null bool field ingestion

* trying to resolve issue when ingesting null value for bool type

* adding a clearing support for bool type

* resolving issues with bool null value ingestion

* updating the jwt go package version and removing changes made in docker compose file

* reverting jwt go version

* removing v4 of jwt

* adding a comment in test file to see if sonar cloud accepts this file
2022-11-15 11:13:42 -08:00
Pranitha-malae
f4dc39bba9 Sync 800750c746 through 9b91023e29 2022-11-15 11:12:19 -08:00
Travis Turner
0e769b1da3 Sync 800750c746 through 9b91023e29 2022-11-15 11:11:40 -08:00
Seebs
f6eacec56c Sync through 011174b631 2022-11-15 11:00:50 -08:00
Seebs
7a58dfe889 Sync through 346dbb04fe 2022-11-15 10:59:13 -08:00
CLoZengineer
dc27e3d1d8
feat: builds docker images for running featurebase from a release (#2193)
* adds dockerfile for building images to run examples on

* adds makefile entries to build and push docker runner images

* cleans up tar artifacts when building ingest runner

* moves executables to /usr/local/bin

* moves the sources for building runner images into their own folder

* simplifies makefile and adds directions to readme
2022-11-08 13:07:17 -05:00
CLoZengineer
daceee2ab6
merge: featurebase merge updates for 2022-10-28 (#2188)
* use t.Fatal(f) to abort tests, not panic

* make perf_able run at all, make it debug a bit better

switch perf-able to using same node type we use for other spot instances,
because otherwise it never finds any available capacity.

we switch the perf-able script to use the standard get_value function
instead of direct jq calls.

we try to grab server logs if the restore fails in the hopes of finding
out why the restore very occasionally fails.

* Fix some issues with running IDK tests in docker. (#2248)

*Stop running TestKafkaSourceIntegration with t.Parallel()

This test can't be run in parallel as it's currently written. Doing so
allows for interleaving of messages to the same kafka topic between
tests.

I didn't attempt to modify the test so it could be run in parallel. That
could be done, but left for someone more ambitious.

* Remove idk/testenv/certs which got accidentally committed.

also update .gitignore to include those.

* changes to add bool support in idk (#2240)

* initial changes to add bool support in idk

* modifying some default parameters for testing, will revert them later

* adding support for bool in making fragments function

* boolean values implementation without supporting empty or null values at this point

* Implement bool support in batch using a map (and a slice for nulls) (#2247)

* Implement bool support in batch using a map (and a slice for nulls)

* Keep the PackBools default for now

But set it explicity in the ingest tests which rely on it.

* Modify batch to construct bool update like mutex

The code in API.ImportRoaringShard has a switch statement which causes
bool fields to be handled like mutex fields. This means, that the
viewUpdate.Clear value should only contain data in the first "row" of
the fragment, which it will treat as records to clear for *all* rows.
This makes more sense for mutex fields; for bool fields, there's only
one other row to clear. But since the code is currently handling them
the same, we need to construct viewUpdate.Clear such that it conforms to
that pattern.

This commit also adds a test which covers this logic.

* Remove commented code; revert config for testing

This commit also removes the DELETE_SENTINEL case for non-packed bools,
since that isn't supported anyway.

* Revert default setting

* remove inconsistent type scope

* correcting the logic of string converstion to bool

* resolving an error in a test

* adding tests to cover code related to bool support in batch.go file and interface.go files

* modifying interfaces test

* added one more test case

Co-authored-by: Travis Turner <travis@pilosa.com>
Co-authored-by: Travis Turner <travis@molecula.com>

* resolving bool null field ingestion error (#2254)

* resolving bool null field ingestion error

* testing issues

* adding null support for bools

* updating the null bool field ingestion

* trying to resolve issue when ingesting null value for bool type

* adding a clearing support for bool type

* resolving issues with bool null value ingestion

* updating the jwt go package version and removing changes made in docker compose file

* reverting jwt go version

* removing v4 of jwt

* adding a comment in test file to see if sonar cloud accepts this file

* don't obtain stack traces on rbf.Tx creation

We thought stack traces were mildly expensive. We were very wrong.
Due to a complicated issue in the Go runtime, simultaneous requests
for stack traces end up contending on a lock even when they're not
actually contending on any resources. I've filed a ticket in the
Go issue tracker for this:

	https://github.com/golang/go/issues/56400

In the mean time: Under some workloads, we were seeing 85% of all
CPU time go into the stack backtraces, of which 81% went into the
contention on those locks. But even if you take away the contention,
that leaves us with 4/19 of all CPU time in our code going into
building those stack backtraces. That's a lot of overhead for a
feature we virtually never use.

We might consider adding a backtrace functionality here, possibly
using `runtime.Callers` which is much lower overhead, and allows us
to generate a backtrace on demand (no argument values available,
but then, we never read those because they're unformatted hex
values), but I don't think it's actually very informative to know
what the stack traces were of the Tx; they don't necessarily reflect
the current state of any ongoing use of the Tx, so we can't necessarily
correlate them to goroutine stack dumps, and so on.

* fb-1729 Enriched Table Metadata (#2255)

enriched metadata for tables

added support for the concept of a table and field owners in metadata; mechanism to derive owner from http request metadata; metadata for table description

* tightened up is/is not null filter expressions (FB-1741) (#2260)

Covers tightening up handling filter expressions that contain is/is not null ops. These filters may have to be translated into PQL calls to be passed to the executor and even though sql3 language supports nullability for any data type, currently only BSI fields are nullable at the storage engine level (there is a ticket to add support for non-BSI field here FB-1689: IS SQL Argument returns incorrect error) so when these fields are used in filter conditions we need to handle BSI and non-BSI fields differently.

* added a test to cover the keyword replace as being synonymous with insert (#2261)

* update molecula references to featurebase (#2262)

Co-authored-by: Seebs <seebs@molecula.com>
Co-authored-by: Travis Turner <travis@pilosa.com>
Co-authored-by: Pranitha-malae <56414132+Pranitha-malae@users.noreply.github.com>
Co-authored-by: Travis Turner <travis@molecula.com>
Co-authored-by: pokeeffe-molecula <85502298+pokeeffe-molecula@users.noreply.github.com>
Co-authored-by: Stephanie Yang <stephanie@pilosa.com>
2022-10-28 13:08:23 -04:00
CLoZengineer
fc1a5dad53
feat: updates shardwidth.Exponent to single constant (#2185)
* removes build time constant in favor of single constant with relevant godoc and warnings

Co-authored-by: Christopher Lowenthal <christopher.lowenthal@molecula.com>
2022-10-25 13:30:00 -04:00
CLoZengineer
f4b58043ba
chore: adds release workflow with basic build step (#2182)
* adds release workflow with basic build step

Co-authored-by: Christopher Lowenthal <christopher.lowenthal@molecula.com>
2022-10-25 10:41:39 -04:00
CLoZengineer
25dbbb2950
chore: adds golangci config (#2174)
* removes rewrite-rules, sets gofmt.simplify to default true

* moves go vet step before the golangci-lint step

* fixes go vet issues with test files

* updates gocognit.min-complexity to default of 30

* removes deprecated options, primarily around run.go version
2022-10-17 11:42:33 -04:00
jonathan.cheng
4e0a844cfb Sync from internal repo through 6035345 2022-10-13 14:44:07 -07:00
Seebs
d4a03f21fb test for correct state during test startup
When we've started a fake cluster, we should expect to reach a
"STARTING" state, not a "DOWN" state. This test would coincidentally
pass as long as we checked the state before any of the nodes got
their notification from the node watcher that at least one node was
STARTING, because prior to that the cluster would be DOWN. But once
it got to STARTING, we would wait forever; we never reached the
instruction to tell the nodes to come to any other state, and they
would never reach a DOWN state.
2022-10-13 14:40:34 -07:00
Julio Martinez
0d7f676ce5 Change featurebase user home path to /var/lib/featurebase. (#2242) 2022-10-13 14:39:54 -07:00
Jacob Brinlee
c5aa05362a adding foreignIndex conf opt (#2239) 2022-10-13 14:39:20 -07:00
Hoang Pham
631d7e84dc FB-1696 - fixed debug message to show topic's name instead of topic's address 2022-10-13 14:38:41 -07:00
Seebs
9b3e236ce5 drop test timeouts to reasonable values 2022-10-13 14:37:55 -07:00
Kasey
5f354dfe1e
Update README.md
Update links
2022-10-13 13:41:54 -07:00
Kasey Rodgers
e75abc3c38 added testify dependency 2022-09-30 11:31:37 -07:00
pokeeffe-molecula
07da547634 moved file from this repo to documentation repo (#2232) 2022-09-30 11:25:27 -07:00
Julio Martinez
3012be083f Remove 30sec restart wait. (#2231) 2022-09-30 11:25:27 -07:00
pokeeffe-molecula
e24978c4a7 And now....INNER JOIN! (#2230)
* ID sql3 internal type representation is int64; fixed a bug that assumed incorrectly that it wasn't

* refactored some names for clarity

* primary: get nested loop joins to work; secondary get  brute force aggregations for SUM working

* added tests; removed debug output

* review feedback

* Update sql3/planner/compileselect.go

review feedback

Co-authored-by: Travis Turner <travis@pilosa.com>

Co-authored-by: Travis Turner <travis@pilosa.com>
2022-09-30 11:25:27 -07:00
HHans09
f194cb216b FB 1646 : Code updated to make the debug message more helpful 2022-09-30 11:25:27 -07:00
HHans09
c60a037065 FB-1646 : UPdated code post code review 2022-09-30 11:25:27 -07:00
HHans09
ad7a41fa06 FB-1646 Removed Debugf messages that does not make sense 2022-09-30 11:25:27 -07:00
HHans09
93c66601be UPdated the code to remove declared but unused variables - committedOffsets, stv & iv 2022-09-30 11:25:27 -07:00
HHans09
d8de30418e Removed Debugf messages that does not make sense 2022-09-30 11:25:27 -07:00
Seebs
331b5a0e36 use testhook test cleanup
The testhook post-test hooks only work if you use a TestMain to
invoke them, otherwise the cleanups can be registered but never
actually get run. This deletes the etcd sockets, and temp
directories, that we created from our test runs. We also fix
the test creating a temp file directly to create it in a TempDir
(which gets cleaned up after the test), and fix the name of the
top-level tests displayed in TestMain.
2022-09-30 11:25:27 -07:00
Seebs
20b018c0b2 remove a commented-out test case for a function that no longer exists 2022-09-30 11:25:27 -07:00
Seebs
44314fc32f drop unused row
This looks like leftover code from an earlier draft. We weren't
using this value.
2022-09-30 11:25:27 -07:00
Seebs
6b008beaec address multiple staticcheck issues
staticcheck notices a bunch of unused values and similar
things, let's fix them while we're here.
2022-09-30 11:25:27 -07:00
Seebs
d4e637eb9b drop ioutil
The ioutil package is deprecated, with all of its functions having
moved into os or io. Do the replacements so we stop having this
impending.
2022-09-30 11:25:27 -07:00
Seebs
ea69b0637d significant refactor of test setup and teardown
We centralize the creation paths for test indexes, fields,
etcetera so they all have a common path, all using standard
test holders. There's still two versions, one for test.* functions
and one for internal. They do share a TestHolderConfig though.

Large hunks of the related APIs are simplified/streamlined.
* Fragments are always created with a Field and don't need
  a workaround in case they don't have it.
* Creation of test fragments, etc., use optional FieldOptions
  but don't specify names because they're all using new holders
  for each thing created anyway. This dramatically reduces
  the complexity of the calls.
* test fragments are created inside test views which are created
  inside test fields, etcetera, so everything is using the same
  logic; test views aren't bypassing the other layers, they're
  creating themselves normally within a field.
* Quite a few things now use the standard runtime/production
  logic instead of being custom workarounds; for instance, instead
  of `mustOpenMutexFragment` creating a fragment and then creating
  a mutex vector for it, we just create a mutex-typed field and
  have the normal runtime code do this.
* Similarly, we now use the same field creation logic that production
  does, instead of having our own test-only thing that validates
  field names directly, so our test that we're validating field names
  is actually testing the runtime code. Yay.
* fragSpec goes away. it was a replacement for fragProxy which existed
  to solve memory allocation problems but replaced them with interface
  overhead problems. Now we just have pointers to things and maintain
  valid data structures.
* Many panics are now Fatal or Fatalf calls.
* Some specific bugs fixed, like a cluster which was requested and
  then had its first node directly overwritten, which isn't valid with
  shared clusters.
* Drop the temp-dir test flag and TempDir variable, we can just use
  $TMPDIR.
* Drop a benchmark of "write file to disk" that was purely a benchmark
  of file write speed, not a benchmark of rendering the data that needs
  to be written.
* Drop the unused "flags" parameter to fragment creation, which was
  only used back when we changed the BSI format.
* Use holder.Txf() rather than index.Txf(). The TxFactory has to be
  holder-level anyway, referring to it via the index is misleading.
* Test holders automatically close themselves and delete themselves,
  we remove various other things that thought they were responsible
  for deleting themselves.
2022-09-30 11:25:27 -07:00
Seebs
bfe52fb900 reduce verbosity of retryablehttpclient
The default client appears to be pretty spammy and flood us with
debug messages about POST and GET requests, and honestly we don't really
need these or benefit from them, I don't think, so let's not.
2022-09-30 11:25:27 -07:00
Seebs
f48733d44d set directory permissions restrictively to quiet etcd 2022-09-30 11:25:27 -07:00
Seebs
367f68f443 restore commented-out test 2022-09-30 11:25:27 -07:00
Seebs
787c9da90b drop excessively verbose messages used while debugging something long ago 2022-09-30 11:25:27 -07:00
Seebs
e8e655cf05 continue removing Tx parameters to view-type functions
A few view functions were taking a Tx, which had to be shard-specific,
but that's sort of awkward -- the view is inherently not shard-specific,
so it should be handling sharding internally.

There were also a couple of remaining obsolete checks for whether a
Tx was nil, at least two of which were in contexts where it absolutely
can't be. Remove all of them, and also the function itself.
2022-09-30 11:25:27 -07:00
rachithrr
e33ab1f92a FB-1674: Kafka consumer stops reading messages from topic (#2222)
Added condition to first sort by topic, followed by partition and offset.
2022-09-30 11:25:27 -07:00
pokeeffe-molecula
448fc81c2e fb-1075 (#2221)
* handle multi field count correctly

COUNT() should ignore null values.
If the data type of the expression supports an existence bitmap for the underlying FeatureBase data type we will use it to eliminate nulls from the aggregate

* simplify aggregate for existence test

we can use a direct != null instead of an indirect not(=null), and
avoid relying on the probably-broken behavior in the executor that
tries to silently fix up Row(x=3) tests on BSI fields which wanted
Row(x==3).

Co-authored-by: Seebs <seebs@molecula.com>
2022-09-30 11:25:27 -07:00
Seebs
bf6d0c1c21 use timeout when waiting for cluster state changes
We had this fail in CI once, and failing took 30 minutes because
we didn't have a timeout on this. This shouldn't ever fail, but
the fact that it did indicates that the fabled etcd failures
we've seen a couple of times were still capable of happening.
This will make that failure happen sooner and more clearly.

Also, log the cluster states (and possibly node states) while
waiting. But add a delay -- otherwise we can do this quite a few
times per millisecond. We use Logf so that, if you didn't use -v,
you see these reported only if the test fails, but if the test fails,
we'll say what happened.

It would probably be better to have a passive thing that can wait
for updates, because we're waiting on heartbeats. Missing: A way to
detect what's actually happening in the failure cases, which we
see only quite rarely.
2022-09-30 11:25:27 -07:00
Seebs
e3afc50d99 staticcheck is right, as usual 2022-09-30 11:24:56 -07:00
Hoang Pham
232fcd5151 FB-1663 - fix make build-lattice failing 2022-09-30 11:24:49 -07:00
Hoang Pham
f9945a403f FB-1339 - UI - updated lodash version to fix gitlab vulnerability 2022-09-30 11:24:43 -07:00
Seebs
130eea3aaa bump to go 1.19.1 because there's no longer a docker image for 1.19 2022-09-30 11:24:32 -07:00
Seebs
cd6125dfc6 squash auth tests into regular smoke tests, improve smoke tests
This is a bit complicated and entangled, sorry.

First, we squash the auth-based smoke tests into the regular smoke
tests; we just run all the tests with auth on and that way we don't
need to spin up an entire separate cluster of machines just to run
a single query against them.

We improve the error detection, and standardize the jq-to-get-config
code. The purpose of this is to try to make sure that, if we actually
hit a failure and get "null" for a host name, we report *that*
as an error, rather than running ahead and producing 20+ separate
reports that ssh failed because it couldn't find a host named null.
2022-09-30 11:23:17 -07:00
Seebs
3671129cd5 don't run commands against holder before messing with its stats
You have to start the cluster before you can refer to its holders,
because GetNode doesn't work on an unstarted cluster, but if you
actually issue any commands, those require messing with the worker
pool which wants to have access to the holder's stats.
2022-09-30 11:22:07 -07:00
Matthew Jaffee
01a0eb0d74 add persistent history and combination of multi-line commands to CLI
"featurebase cli" will now save command history to
$HOME/.featurebase/cli_history by default. Additionally if a command
is entered across multiple lines, the newlines will be removed when
the command is saved in the history. Previously each line was saved
separately which was a bit annoying.
2022-09-30 11:22:07 -07:00
pokeeffe-molecula
7bbfc8e5e9 Add a smoke test for the sql3 endpoint (#2214)
* turned on sql endpoint in smoke test; added a test to execute a simple sql statement

* add config to both configs

* fixed not enough arraying
2022-09-30 11:21:56 -07:00
Garrison Davis
0d8393ddcf Fix UUID library version for CVE-2021-3538 (#2213)
We were using v1.2.0 of the github.com/satori/go.uuid library to
generate UUIDs for transactions if the transaction had no previous id.

That version of the library had CVE-2021-3538: "Due to insecure
randomness in the g.rand.Read function the generated UUIDs are
predictable for an attacker."

More reading can be done here:
https://pkg.go.dev/vuln/GO-2022-0244
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3538

This vulnerability was found using the new govulncheck tool which is not
currently used in our CI pipeline but might be a good candidate to
include in the future. (Like all tools like this there are caveats to
its usage and utility which can be read about below.)

Information on that tool can be found here:
https://go.dev/blog/vuln
https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
2022-09-30 11:21:11 -07:00
pokeeffe-molecula
15382a2863 sql3 changes (#2211)
* first cut of working (slowly) bulk insert; table valued functions and a tuple data type to support time quantums

* oversight

* filter pushdown implementation; bulk insert

* addressed some linter issues
2022-09-30 11:21:11 -07:00
Seebs
e47bdb7889 cleaned up sync from private repo 2022-09-30 11:20:58 -07:00
Seebs
f6d17b1b58 refactor testing to share clusters more often
When doing tests, we create a ton of one-off clusters. This
turns out to be expensive and slow. Fixing it is surprisingly hard.

Fundamentally: If we're sharing clusters, we need to use different
indexes for each test, to avoid clashes. This changes index names.
As a side-effect, this reorders many partition-based things, like
the order keys are returned in. Thus, to fix this, we change a lot
of tests to no longer depend on the *order* in which strings are
returned.

Having done that, we can also discard the ModHasher behavior, since
that only existed to allow us to reliably predict partitioning.

The basic design is as follows: Instead of a cluster being a
[]*Command, a "shareable" cluster is now a []*Command plus some
flags, and a "cluster" is a pointer to a possibly-shared cluster,
plus a link to the specific test using this specific cluster,
and correspondingly, its test name suitably coerced to be a valid
index name prefix.

The "test.Cluster" object now has methods to allow retrieving an
index name, and also implemnts fmt.Formatter to let you use,
e.g., `%i` with it in Sprintf to get "the index name, plus an i".
(This works for everything but %p and %T.)

This allows us to consistently rework all the many things that
use index names in a persistent way.

We also have `MustUnshared` and `MustRunUnsharedCluster` methods
which allow us to specify that a given test needs its own cluster
for some reason. For instance, the tests that want to run backups
need their own isolated cluster, and the tests that want to close
or reopen nodes need their own cluster because a reopened cluster
won't have working GRPC for some reason.

On "closing" a shared cluster (actually the test-specific wrapper
that reflects a given sharing), we delete any indexes starting with
that test's index name prefix. Otherwise, the huge pile of open
indexes prevents `go test -race` from working on MacOS, where we
run out of address space too quickly.

This is fairly enormous but most of the individual changes are
fairly trivial things like replacing the string "i" with "c.Idx()".

We also tweaked a test that failed for me a couple of times to
not depend on sort order.
2022-09-30 11:10:47 -07:00
Seebs
799e70fe46 shorten SetValue_QuickCheck
We reuse a fragment. It might seem surprising that this works, but
the fragment code actually doesn't have a persistent bit depth at
all, it just accepts whatever bit depth you tell it to use. Cutting
out the recreation of the fragments saves some time.

We also cap bit depth at 8, instead of 62, because there's a ton
of runtime cost to testing more bit depths, but it doesn't actually
change the logic.
2022-09-30 11:10:47 -07:00
Seebs
904b19dce1 reduce simultaneous memory usage a bit
Delete indexes after we're done with them from subtests so that
we don't fill up on a huge number of unrelated indexes.
2022-09-30 11:10:47 -07:00
Seebs
fb3e60f88a set RBF sizes smaller for test
We end up hitting race detector limits on MacOS. This should mitigate
that.
2022-09-30 11:10:47 -07:00
Seebs
dad8211709 fix silly math typo
For arbitrary mod values m, greater than zero,
	(x%m + 1) != 0
is always true

What we almost certainly meant was
	x%(m+1) == 0

which would give you all the bits in row 0, half the bits in row 1,
etcetera.

Also, we drop to doing a quarter-shard because why not.
2022-09-30 11:10:47 -07:00
Seebs
6207da9c48 reduce size of KeyReplication test
This test used to be large, because it was testing some features that
were refactored out in October of 2019. Since we no longer have the
"buffer growth" to check, let's check a much smaller file.
2022-09-30 11:10:47 -07:00
Seebs
c1ee7d5a5c improve post-hook behavior
We want to be able to register hooks which do cleanup, which may be
registered after the auditor cleanup check, which means that we
want LIFO order for post-hook cleanups.

We also want the test hook cleanup to be deferred, rather than
merely run after the tests are executed. Also, we have to extract
the result from running the test, then execute deferred things,
*then* call os.Exit, because os.Exit bypasses defers.
2022-09-30 11:10:47 -07:00
Seebs
964e7d86c8 kill everything that tries to pass nil tx to field/view things
The "field/view will just synthesize a tx" behavior is awful and
also hides a number of fundamental flaws. We distinguish between
"we really do mean to work on a single shard here" and "we intend
to work on the whole field or view", and the latter now take
Qcx instead of Tx.

This eliminates a lot of very weird cases where we checked for
nil Tx and synthesized them, and also gets us away from
field and view taking Tx parameters when no possible Tx
can be constructed which is valid, because Tx are inherently
shard-specific at this time.
2022-09-30 11:10:47 -07:00
pokeeffe-molecula
204558b46f added /sql endpoint; implemented SHOW TABLES (#1935)
* squashed 45 commits into one :)

* tlt/sql experiment (#2035)

* Move PlanOperator to sql3/planner/types package

includes:
type PlanOperatorColumn struct
type PlanOperator interface

* Remove planner dependencies from pilosa package

The goal after this is to prevent the planner package (which doesn't exist yet)
from being imported by the pilosa package; we just want it injected into the server
in server/server.go. This is because the planner package uses pilosa types, so we need
to avoid circular dependencies.

Added ExecutionPlannerFn
Make public: pilosa.ExecOptions
Added a pilosa.Executor interface
Added a planner.types.CompilePlanner interface
Isolated the planner calls to:
- Executor.Execute()
- *API.[method]()

* Move executionplanner files into the sql3/planner package.

This required a bit of gymnastics, and there are some things around
FieldOptions which need to be addressed soon.

* Remove the hacky FieldOptions stuff I added earlier

This implementation just uses the pilosa.FieldOption functional options
provided by the API (as opposed to trying to build a FieldOptions
object.

It also changes field types to constants. These are private for now, but
if we need to make them public, we should put them in the planner/types
package.

* Implement the "scale" value from Decimal(scale)

Also, precision and scale were currently reversed in the parser. This
fixes that.

* Modify the parser to handle CACHETYPE <type> SIZE <size>

It's a little odd to me that the cache type values are Tokens, but I
guess it's ok. One thing to keep in mind is that FeatureBase expects
lowercase values, so this commit changes the parser to set the value to
the lowercase version of the type.

* Fix the /sql2 tests

This entailed a combination of commenting out or t.Skip()-ing tests
which covered code in the parser that has been commented out or removed
as not currently supported in sql3.

It also adds some coverage for the sql.Contraint stringers.

* Prevent JSON sql results from containing closing commas

This commit just re-works the existing output code to avoid inserting
closing commas (which results in invalid JSON).

* Enhance the CREATE TABLE test coverage.

In particular, ensure that the fields which get created in FeatureBase
are what we expect based on the fields defined in the CREATE TABLE
statement.

This also ensures that the TIMEQUANTUM and CACHETYPE contraints are not
provided for the same field (since those constraints are not supported
together).

* Adjust the EBNF file to indicate SIZE contraint is optional

A CACHETYPE can be provided without a SIZE. This change indicates that
SIZE is optional.

* Remove `executionplanner_` from file names (#2040)

* implementation of ALTER TABLE (sans column RENAME)

* refactored expression analysis; added more robust type checking; all unary and bin ops function on ints

* added type support for expressions; full bin/unary op support; added cast; more literal support

* cast int to all other types

* all literals (except idset, stringset & timestamp) make it thru; cast to all types with int as source now works

* implemented LIKE/NOT LIKE

* Implemented IS [NOT] NULL

* Move sql2 files into sql3/parser package (#2045)

* Move sql2 files into sql3/parser package

This also removes the sql2 package.

* Fix tests which were typing _id fields as INT intead of ID

* implemented BETWEEN, NOT BETWEEN

* Add featurebase/error package (#2046)

* Add featurebase/error package

I copied the `dax/errors` package which I am starting to use in the DAX
prototype into `featurebase/errors` in order to start using it with the
sql3 package. It's basically a wrapper around `github.com/pkg/errors`,
but it uses a customer coded error.

The sql package can define its own errors based on the
`featurebase/errors` types. Then do things like `Wrap()` and `Is()`.

* Address the linter complaints: shadowed variables, unreachable code

* implemented IN & NOT IN with expression lists

* first cut of CASE

* Fixed some errors from rebase

* updated bnf; removed unused code; tightened up error handling

* first crack at basic CLI for SQL3

Use: `featurebase cli`

Still lots to do here, but for example:

> select count(*) from tremor
+--------------+
|        COUNT |
+--------------+
| 1.158321e+06 |
+--------------+

* Iterate on the CLI (#2057)

Handle the errors.
Add an "exit" command.
Add some general formatting and white space.

Add termination character: ";" (semicolon)

This commit allows a user to provide multiple or partial SQL statements.

Example of multiple statements:
```
show tables; select * from foo;
```

Example of partial (multi-line) statements:
```
select *
from foo;
```

Don't uppercase the header values

* error refactoring; first cut of TOP; remove unused code; use log.Printf instead of fmt.Printf

* fixed a bug with QualifiedRef from refactoring; added bones of INSERT; removal of unused code; tightened up errors more; fixed failing tests

* single value list for INSERT

* Update bnf per discussion with Travis; INSERT now doing the requisite stuff

* Pat's eyes went square - nothing wrong with TOP, Pat needed to learn arrays again.

* improved some errors; fixed tests to suit

* send warnings back in the api; update CLI to display warnings

* start warning on stuff not implemented so we don't get bugged about it

* Tlt/sql experiment (#2063)

* Expresssion -> Expression

* Add SQL planner test

- adds a test to which it is easier to add tables and SQL statments
- un-exports all of the expression types
- removes the planner pointer from the expression types (it can be added
  back later if need be)

* Fix where clause on a string field

Prior to this commit, the binary expression for a where clause on a
string field was building the call by providing a range operator which
is typically used for BSI fields. This changes it to use the call.Args
for string values.

* Update planner tests to handle multiple sql for the same results

* Reorganize SQL tests

Introduce a test/helpers package and move shared MustQueryRows into that
package.

* Add a compatibility map for field types. (#2064)

This is primarily to address the fact that ID fields were previously
incompatible with INT literals.

We should probably consider introducing a custom type for FieldType
which can be used to define compatibilities.

* significantly refactored type checking

* Handle nil (NULL) values in the sql CLI. (#2067)

go-pretty panics if the interface{} field value is nil. This replaces
nil values with a "NULL" string.

* Squash some commits

fixed a still failing test

added line, col to all error messages

refactored source handling to enable table aliases

fixed some copypasta per review

warnings for order by & topn; implemented select as a source

starting to handle in (select...); added stub for optimizer

JSON-encode the sql error and warning strings (#2069)

Error strings with unencoded characters (like double quotes) were
resulting in invalid json.

got insert working; added symbol table; added concrete optimizer; added nascent NestedLoopsOperator; rewrite "where foo in (select..." as inner join

* all about the sets (#2085)

* implemented setcontains()

* implemented set literal; insert set column values; setcontains/all/any both in expr eval and pql filters

* Convert test to use latest framework. (#2086)

* fixed some comments

* removed refactored tests

Co-authored-by: Travis Turner <travis@pilosa.com>

* Add support for Decimal fields to the sql test. (#2090)

* dates (#2094)

* return dates as strings in output; tightened up decimal type checking

* return dates as strings in output; tightened up decimal type checking

* fixed failing tests after decimal changes

* can now insert decimal values

* implemented insert for timestamp data type; implemented current_date, current_timestamp constants

* fixed some failing tests

* handle date literals from strings in insert statements

* changes from feedback

* Fix pointer method error

* sql3 API interface (#2110)

* Introduce API-related interfaces: SchemaAPI, ComputeAPI

The sql3 code was relying on the pointer: *pilosa.API in order to call
API methods directly on the local node. If we want to import and use the
sql3 package in another service (the DAX queryer, for example), we need
to be able to use an implementation of an interface for those API method
calls.

This commit introduces two interfaces, both automatically implemented by
pilosa.API:
- SchemaAPI
- ComputeAPI

* Convert sql3 code to use IndexInfo instead of Index

The sql3 code was relying on a *pilosa.Index and its methods to get
general information like index and field name, type, etc. This commit
converts everything to use a *pilosa.IndexInfo instead.

This allows us to modify the SchemaAPI interface to also return
IndexInfo instead of Index, which will be a lot easier to implement in a
non-pilosa package (like DAX); creating a *pilosa.Index requires
providing things like data directory paths and holders, which are not
necessary for these use cases.

* Unary and Binary Ops R US plus CAST (#2111)

* implemented string literal for timestamp epoch

* fixed failing test

* fixed the failing test again

* refactored tests; implemented unary op tests for all datatypes; implemented binop tests for int/int, int/id, int/decimal & ID/int

* implemented all binary ops for INT & all other types, ID & all other types

* implemented binary ops for DECIMAL types & all other types

* added STRING & BOOL to various tests; implemented all remaining binOp tests

* fix up some stuff after rebasing

* refactored test defs into multiple files; implemented CAST for every datatype

* added tests for like/not like

* addressed review feedback

* addressed type review feedback

* tightened up IS [NOT] NULL behavior plus tests (#2118)

* tightened up IS [NOT] NULL behavior plus tests

* BETWEEN/NOT BETWEEN with all data types

* addressed review feedback

* Handle negative integers in column min/max constraints (#2120)

This commit parses the min/max contraint as an expression, as opposed to
an int literal, so that negative values are treated as Unary
expressions.

There currently isn't support for min/max constraints on `decimal`
fiels, so for now this change only expects +/- integer values.

* Implement the CREATE TABLE keypartitions logic (#2123)

* Execution time, IN/NOT IN & multiple aggregates (#2124)

* added display of execution time

* IN/NOT IN tests for all data types

* fixed date parsing

* removed duplicative tests

* refactoring aggregates

* suport multiple aggregates

* Address review feedback

* final round of feedback

* Add method SchemaAPI.CreateIndexAndFields() (#2127)

In order to support a CREATE TABLE statement as a single command, this
commit alters the SchemaAPI interface to contain a single method which
handles both the index and its fields. It also updates the sql3 code to
use this interface instead of CreateIndex() and CreateField()
indepedently.

* Symbol Handling (Again) (#2129)

* Refactored symbol handling in the planner; re-instated the select as source tests

* removed commented out code

* addressing review feedback

* Move hard-coded _id field out of planner and into interface implementation (#2130)

This commit moves the hard-coded addition of the `_id` field from the
planner to the SchemaAPI.IndexInfo() implementation method.

NOTE: If anything was expecting SchemaAPI.Schema() to also return the
`_id` field as part of its field list in each table, then it would not
be there because the `_id` field is only added in the IndexInfo() method
for now. Currently that's not a problem because nothing is expecting the
`_id` field for `Schema()`.

* Multiple aggregates, all aggregates stand alone and in GROUP BY (#2132)

* handle multiple aggregates in group by queries

* added handling for avg() aggregate both stand alone and in group by

* tightened up sum & avg outside of group by

* added min, max & percentile

* added warnings

* Make MaterializedRowSet implement the PlanOperator interface. (#2133)

This commit refactors the PQLMultiGroupByOperator to have a PlanOperator
as its output. Then, when it initializes, it sets up a
MaterializedRowSet and populates that with the values from the multiple
group by operations.

* added explicit min/max pql operators

* saved a file I forgot to save

* per review

* Un-indent some if/else nesting (#2136)

Co-authored-by: Travis Turner <travis@pilosa.com>

* Add optional `name` argument to test structs.

This commit adds the `name` argument to `tableTest` and `sqlTest` so
that a test can be optionally named. This allows a developer to more
easily run/identify a particular test by name.

* Inbuilt functions (redux) (#2141)

* set functions type parameter type checking

* implemented datepart

* include SQL3 type in SHOW COLUMNS output

* fixed select as source; failing SHOW COLUMNS test

* select in select list

* dump output columns; handle optimization for select list subqueries

* make it an error to return multiple rows for a select list subquery

* added description

* contants and test coverage for datepart function

* SQL3 Refactor-palooza (#2182)

* removed unneeded IsAggregate()

* first cut of working nested loops operator aka INNER JOIN

* remove selectListItemPlanExpression

* added some warnings

* all the tests are passing again!

* addressed some linter complaints

* added basic order by

* bug fixes; added 'or replace'/'replace' to insert

* for insert references should return appropriately

* added back ability to use subquery singleton expressions

* removed dead code; fixed test

* json-able plan, Schema() plus refactoring

* fixed dumb code

* add some tests for time quantum behavior

* Code cleanup during review. Also fixed INSERT to keyed table bug.

This commit contains a lot of minor adjustments made during code review.

It also contains a bug fix that was preventing INSERT into a keyed table
(i.e. _id type STRING) from working.

Co-authored-by: Travis Turner <travis@molecula.com>

* Fix expected min/max on timestamp column test (decimal field)

I don't know why this changed, but presumably something to do with
decimal related work that happened on master.

* Fix compile problem after rebase

* review feedback

Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
Co-authored-by: Travis Turner <travis@pilosa.com>
Co-authored-by: Travis Turner <travis@molecula.com>
Co-authored-by: Fletcher Haynes <fletcher@capitalprawn.com>
2022-09-30 11:10:24 -07:00
Hoang Pham
8b8f14a6bc FB-1627 - Added backup/restore tar. Purpose: for cloud team to backup and restore directly through stdout, stdin 2022-09-30 11:06:32 -07:00
CLoZengineer
f9ddb5d5c1
fix: updating code to meet linting requirements (#2171)
* removes unused filesize function

* removes ioutil usage

* updates ioutil.ReadAll to io.ReadAll

* updates ioutil.TempFile to os.CreateTemp

* updates ioutil.TempDir to os.MkdirTemp

* updates ioutil.ReadAll to os.ReadAll

* update ioutil.WriteFile to os.WriteFile

* updates ioutil.Discard to io.Discard

* updates ioutil.ReadDir to os.ReadDir where applicable

* removes unused code in idk

* creates type to use for context value keys

* replaces assert.Nil with assert.NoError for error checks
2022-09-29 12:34:29 -04:00
CLoZengineer
51249cda78
chore: creates ci.yml workflow (#2167)
Creates our basic CI/CD workflows

Co-authored-by: Christopher Lowenthal <christopher.lowenthal@molecula.com>
2022-09-22 17:09:59 -04:00
CLoZengineer
e61ef2a4da
fix: fixes unkeyed composite literal (#2168)
Co-authored-by: Christopher Lowenthal <christopher.lowenthal@molecula.com>
2022-09-22 10:45:37 -04:00
hphamMolecula
f07dc61617
Merge pull request #2164 from FeatureBaseDB/2161-build-lattice-makefile-target-failing
Fix issue #2161 build lattice makefile target failing
2022-09-13 11:23:07 -05:00
Hoang Pham
40d9f9a834 Updated package.json to use @types/react": "^17.0.0 in devDependencies and resolutions 2022-09-08 16:20:10 -05:00
Fletcher Haynes
383ce50b95 Updated Dockerfiles for lattice to use a publicly available container in the GitHub container registry 2022-09-08 11:05:43 -07:00
Fletcher Haynes
0c19c87a40 Merge branch 'master' of github.com:pilosa/pilosa 2022-09-06 09:39:51 -07:00
Fletcher Haynes
da9b57bd45 Updated dependency paths to reflect new repo location 2022-09-06 09:39:22 -07:00
Kasey
acf94f318b
Merge pull request #2160 from FeatureBaseDB/README-corrections
chore:correct README typo
2022-09-02 14:03:28 -07:00
Kasey Rodgers
6d326a4974 chore:correct README typo 2022-09-02 13:58:44 -07:00
Fletcher Haynes
eb06bb50ae Updated code to latest version for open-sourcing. 2022-09-02 13:23:39 -07:00
Matthew Jaffee
227632544d
Merge pull request #2150 from pilosa/slack-link
Add slack link to readme
2021-12-14 10:56:22 -06:00
Alan Bernstein
0c39f7e4ea
Add slack link to readme 2021-12-13 20:16:11 -06:00
Travis Turner
8886da126f
Merge pull request #2137 from travisturner/backport-fix
fix interface{} -> bool err
2021-01-27 08:13:04 -06:00
Travis Turner
4681d50988
remove leftover commented code 2021-01-27 07:55:15 -06:00
wanggy
53c1fb6bbe
fix interface{} -> bool err 2021-01-26 21:53:13 -06:00
alanbernstein
d960d2fda9
Merge pull request #2130 from alanbernstein/temper-wsl-reference
Remove WSL references
2020-10-23 16:32:29 -05:00
Alan Bernstein
dd4572a4ca Remove suggestion of Windows support 2020-10-23 12:13:03 -05:00
Travis Turner
052440974a
Merge pull request #2125 from travisturner/fix-language-link
fix languages.txt link
2020-09-10 16:18:02 -05:00
Travis Turner
efd5663cc4
fix languages.txt link 2020-09-08 16:41:14 -05:00
Kuba Podgórski
689776b1c0
Merge pull request #2122 from kuba--/notfound-verbose
Make not found error more verbose (add name)
2020-08-27 21:56:32 +02:00
Kuba Podgórski
1f32fe05b0 Make not found error more verbose (add name) 2020-08-27 19:45:19 +02:00
Kuba Podgórski
55353a2567
Merge pull request #2119 from kuba--/union-run-run
Add unionRunRunInPlace
2020-07-16 12:37:01 +02:00
Kuba Podgórski
730fab38dc Add unionRunRunInPlace 2020-07-14 15:10:26 +02:00
Travis Turner
9dc1775b93
Merge pull request #2112 from travisturner/block-edge
Fix off-by-one maxRowID in block limits
2020-05-04 21:54:04 -05:00
Travis Turner
56adbfedfd
Fix off-by-one maxRowID in block limits 2020-05-04 17:29:53 -05:00
Kuba Podgórski
9426b9ee60
Merge pull request #2111 from kuba--/fix-groupby-iter
GroupBy should terminate even if the last result is empty
2020-04-29 16:07:39 +02:00
Kuba Podgórski
5f4a1d1668
Merge branch 'master' into fix-groupby-iter 2020-04-29 11:14:32 +02:00
Kuba Podgórski
1b3d0fd8a9
Merge pull request #2104 from sundy-li/holder-fix
holder.go: fix some logic errors
2020-04-29 11:14:11 +02:00
Kuba Podgórski
8678bc52ba
Merge branch 'master' into fix-groupby-iter 2020-04-27 17:51:13 +02:00
Kuba Podgórski
4e16a4c489
Merge branch 'master' into holder-fix 2020-04-27 17:50:26 +02:00
Kuba Podgórski
9cf9968b64
Merge pull request #2110 from seebs/roaring4go
Handle file sizes over 4GB
2020-04-27 17:49:44 +02:00
Kuba Podgórski
816b015cf3
Merge branch 'master' into holder-fix 2020-04-27 12:47:09 +02:00
Kuba Podgórski
06675c2f9c GroupBy should terminate even if the last result is empty 2020-04-27 12:43:15 +02:00
Seebs
827923e616 Handle file sizes over 4GB
We only have 4 bytes for offsets, but what if a file is
over 4GB? Someone came to us with a file with 265 *million* containers,
in a single fragment, which means that over 3GB of their 4.7GB file
is actually just the container headers alone. But we can't easily make
the offsets larger, or change the file format.

So we don't. We just track how many 4GB hunks of the file we've
been through and bump that every time the 32-bit offset wraps. And this
appears to... just work.

This is fixed for both the roaring iterator and the old unmarshalBinary
logic. The logic to handle this will work on 32-bit hosts in the sense
that it will correctly error out for excessively large file sizes or
container counts, but it doesn't actually handle the large files since
it can't.
2020-04-24 10:56:24 -05:00
Travis Turner
72d5081a44
Merge pull request #2105 from zhanglistar/master
1. modify unprotectedGenerateResizeJob to return early iif resizing job
2020-04-11 10:13:26 -05:00
Travis Turner
f4d1122fbc
Merge branch 'master' into master 2020-04-11 09:51:47 -05:00
zhanglistar
93b6adbf65 1. modify unprotectedGenerateResizeJob to return early iif resizing job
not null
2020-04-11 22:48:28 +08:00
Travis Turner
f5c2546c37
Merge pull request #2087 from travisturner/cache-size-none
Fix cacheSize when cacheType is none (and cacheSize is 0)
2020-04-09 09:29:18 -05:00
Kuba Podgórski
9cdaff542f
Update field_internal_test.go 2020-04-09 15:04:34 +02:00
Kuba Podgórski
4272693641
Update field_internal_test.go 2020-04-09 15:04:11 +02:00
Kuba Podgórski
b43065625a
Merge branch 'master' into cache-size-none 2020-04-09 12:37:44 +02:00
sundy-li
768c709937 holder.go: fix some logic errors 2020-04-08 16:35:42 +08:00
Kuba Podgórski
eb73042e82
Merge pull request #2100 from PierreF/runCountRange-bug
Fix offset-by-1 in CountRange with continuous bits interval
2020-03-17 18:57:27 +01:00
Pierre Fersing
e8ca41e522 Fix runCountRange when range start == interval start
When the interval is a proper superset of the range with start equal to
interval start, the range must be considered a superset or it will be
completly ignored (since it neither a subset nor it overlaps)
2020-03-13 10:47:39 +01:00
Kuba Podgórski
ac3a4abb4a
Merge pull request #2099 from kuba--/test-clear
Add extra Clear test (check if existency column bit is set)
2020-02-13 16:11:24 +01:00
Kuba Podgórski
377d14081a Add extra Clear test (check if existency column bit is set) 2020-02-13 15:20:03 +01:00
Kuba Podgórski
771cc3ae94
Merge pull request #2098 from kuba--/fix-2097
Update handler.go
2020-02-05 23:45:07 +01:00
Kuba Podgórski
4f0740ae4f Update handler.go 2020-02-05 22:17:45 +01:00
Kuba Podgórski
8ec1fef68a
Merge pull request #2096 from kuba--/simplify-holder
Simplify Holder's logic
2020-02-04 00:56:11 +01:00
Kuba Podgórski
b9fa6da5d2 Simplify Holder's logic 2020-02-03 18:12:15 +01:00
Travis Turner
7a032e62f0
Merge pull request #2088 from travisturner/test-2084
Add a test for pilosa/#2084
2019-11-13 10:12:21 -06:00
Travis Turner
4fb0712dab
add a test for pilosa/#2084 2019-11-12 12:05:36 -06:00
Travis Turner
8d716457d1
Merge pull request #2084 from travisturner/import-value-cache
Add logic that clears fragment.rowCache after importValue
2019-11-11 17:16:00 -06:00
Travis Turner
9273691e8d
move requiredDepth calculation after min/max ranges are checked
Without this, a data set with a ludicrously large value in it
could break a BSI field's depth even though the import would then
reject it.

always treat BSI fields as having at least their depth:

If you imported only small values, BSI fields could end up
not bothering to clear higher bits in existing values, which
produced strange behaviors.
2019-11-11 16:48:14 -06:00
Travis
4af91faa7e
fix cacheSize when cacheType is none (and cacheSize is 0)
There was an edge case where setting cacheType to none
wouldn't zero out its cacheSize. This fixes that edge case.
2019-11-08 17:12:35 -06:00
Travis Turner
020b72abbf
reset fragment.rowCache after importValue 2019-11-06 13:19:12 -06:00
Matthew Jaffee
9d7ef20206
Merge pull request #2081 from jaffee/client-cert-tls
Fix authentication of client certs between cluster nodes
2019-10-25 09:27:53 -05:00
Matt Jaffee
b67999215c
fix loop lint 2019-10-22 12:58:56 -05:00
Matt Jaffee
63116e4a83
regenerate certs with 100 year expiration, add README 2019-10-22 12:56:57 -05:00
Matt Jaffee
2651bfbd88
test and fix authentication of client certs btwn cluster nodes
This change should have been adding the "GetClientCertificate"
function in server/tlsconfig.go. This is in addition to the
GetCertificate func which is only used by servers. It ended up being
much more involved for a few reasons:

1. We had no way of passing a configured HTTP client into the
translate store stuff.

2. Our cluster tests assumed http, not HTTPS, and didn't have any way
to pass the necessary configuration in.

3. I encountered what turned out to be an unrelated bug in
cmd/server_test.go which is why I moved "close(m.Started)" in
server/server.go. Basically, I was running something on port 10111
which caused the test to fail (because it was trying to bind to that),
but the failure was not immediately caught during server startup
because the m.Started channel got closed which allowed the test code
to fall through to where it called m.Close() which then got a nil
pointer exception because m.Handler had never been set up.

4. Our test code was assuming that it could create clients that
ignored the config, which meant they didn't do TLS. I added an
InternalClient() method to pilosa.Server to expose the configured
client.
2019-10-18 15:17:35 -05:00
seebs
0b358c6c80
Merge pull request #2074 from seebs/seebs/breakbad
use labeled targets for break statements
2019-10-11 16:05:44 -05:00
Seebs
ef40a5a219 double the nolint comments, double the checking 2019-10-11 15:17:51 -05:00
Seebs
6852df5255 version-bump golangci-lint
These were caught in part by newer versions of golangci-lint,
so let's bump our version of golangci-lint.

[Narrator: The new version would catch more problems, which
would require another commit to fix them.]
2019-10-11 14:50:37 -05:00
Seebs
e5ffed35a4 use labeled targets for break statements
break in a select in a for terminates the current case of the
select, but does not terminate the for loop. The worker queue
implementations for opening indexes/fields/views all suffered
from the same issue here.

Also fix a `<= 0` on a uint value.

All hail staticcheck.
2019-10-11 14:44:25 -05:00
Ben Johnson
1dad949142
Merge pull request #2042 from benbjohnson/per-index-translation-store
TranslationStore Refactor
2019-10-09 09:29:05 -06:00
Ben Johnson
e844e1ad75
Translation store refactor 2019-10-09 08:59:41 -06:00
Ben Johnson
f9e478722c
Upgrade to v2 (#2072)
Upgrade to v2
2019-10-09 07:34:42 -07:00
Ben Johnson
c7c9c1e1d7
v2.0.0
Co-authored-by: Cody Soyland <codysoyland@gmail.com>
2019-10-08 14:56:17 -06:00
Cody Soyland
61dace4527
Merge pull request #2069 from codysoyland/tls-autoreload
Auto-reload TLS certificates on SIGHUP
2019-10-04 10:15:12 -05:00
Cody Soyland
406016dac9 Update license information 2019-10-03 12:20:52 -05:00
Cody Soyland
b98a523b8b Add license header and fix lint warning 2019-10-03 09:59:49 -05:00
Cody Soyland
be91ee2103 Copy dependency into project and use pilosa's logger 2019-10-03 09:44:48 -05:00
Cody Soyland
4324059325 Auto-reload TLS certificates on SIGHUP 2019-10-02 17:10:32 -05:00
Cody Soyland
74b1bb853e
Merge pull request #2068 from codysoyland/mutual-tls
Add support for TLS client certificate verification and custom CA
2019-09-25 15:57:37 -05:00
Cody Soyland
8e06bb5ff3 return error instead of fatal 2019-09-25 15:15:33 -05:00
tgruben
876493c67d
Merge branch 'master' into mutual-tls 2019-09-25 14:49:56 -05:00
Matthew Jaffee
b42f4ae320
Merge pull request #2067 from jaffee/2066-create-field-race
2066 create field race
2019-09-24 14:57:15 -05:00
Cody Soyland
0ec9d3b7e6 Add support for TLS client certificate verification and custom CA 2019-09-24 11:09:58 -05:00
Matt Jaffee
07f8f5b8e0
fix concurrent field creation race condition 2019-09-23 07:54:01 -05:00
Matt Jaffee
ac8c4ed5fe
add concurrent field creation test 2019-09-23 07:51:04 -05:00
Cody Soyland
a24482e44d
Merge pull request #2065 from codysoyland/release-v1.4.0
Release v1.4.0
2019-09-17 17:17:01 -05:00
Cody Soyland
3f7067f895 Add Pilosa 1.4 upgrading instructions to docs 2019-09-17 16:33:35 -05:00
Cody Soyland
c8f8687a22 Fix typo 2019-09-17 16:01:21 -05:00
Cody Soyland
7e9d95f307 Add warning about int fields 2019-09-17 16:01:21 -05:00
Cody Soyland
6efde37fb4
Update CHANGELOG.md
Co-Authored-By: alanbernstein <alanaaronbernstein@gmail.com>
2019-09-17 15:59:28 -05:00
Cody Soyland
53365ed967 Release v1.4.0 2019-09-17 14:47:59 -05:00
Cody Soyland
69f3acac5c
Merge pull request #2064 from codysoyland/ci-updates
Update CirleCI build with Go 1.13 and run enterprise tests
2019-09-17 14:20:52 -05:00
Cody Soyland
3db1a91fa0 Add minimum Go version to go.mod 2019-09-17 13:40:16 -05:00
Cody Soyland
aa7030a646 Update Go version in Circle dependencies 2019-09-17 13:40:05 -05:00
Cody Soyland
8e208569e8 Remove build tag that break enterprise build 2019-09-17 13:34:28 -05:00
Cody Soyland
f8f9d0e3d1 Update golangci-lint 2019-09-17 13:33:54 -05:00
Cody Soyland
ce59aa102e Update CirleCI build with Go 1.13 and run enterprise tests 2019-09-17 12:58:35 -05:00
alanbernstein
f1216fd35d
Merge pull request #2054 from alanbernstein/query-language-fixes
Minor fixes to query language docs
2019-09-17 11:27:34 -05:00
alanbernstein
b17fd34ad9
Merge branch 'master' into query-language-fixes 2019-09-17 09:02:23 -05:00
alanbernstein
a99294a30e
Merge pull request #2063 from alanbernstein/docs-fixes-again
Add Groupby and Rows to glossary, fix small issues
2019-09-16 17:02:01 -05:00
Alan Bernstein
01cfd4adcf Add Groupby and Rows to glossary, fix small issues 2019-09-16 13:34:56 -05:00
alanbernstein
cc05218592
Merge pull request #2062 from alanbernstein/docs-typo-fixes
Minor formatting and typo fixes
2019-09-13 22:20:46 -05:00
Alan Bernstein
7eb68dd99a Minor formatting and typo fixes 2019-09-13 16:40:56 -05:00
Alan Bernstein
f7554a3cd4 Add GroupBy filter response, use sensible field names 2019-08-14 11:37:21 -05:00
Alan Bernstein
af954322cf Minor fixes to query language docs 2019-08-13 14:54:52 -05:00
seebs
bc9747cc0f
Merge pull request #1988 from seebs/startupspeed
WIP: address some startup speed and performance issues
2019-08-07 12:38:52 -05:00
seebs
484c51b6e0
Merge branch 'master' into startupspeed 2019-08-07 11:32:56 -05:00
Matt Jaffee
b84eada521
rename file and add license header 2019-08-07 08:09:04 -05:00
seebs
1e99c5346f
Merge pull request #2 from jaffee/startupspeed-breakout
generalize test strings and break out old UnmarshalBinary code
2019-08-05 18:01:16 -05:00
Matt Jaffee
fba496bc91
generalize test strings and break out old UnmarshalBinary code
(don't use iterator for unmarshalBinary)
2019-08-05 17:39:47 -05:00
Travis Turner
a5aa6e48a5
Merge pull request #2050 from travisturner/bsi-base-value
Default BSI base value to min, max, or 0 depending on the min/max range
2019-07-31 13:06:51 -05:00
Travis Turner
96e6c11897
add bsiBase() helper function to avoid duplication 2019-07-31 12:43:05 -05:00
Travis Turner
9e9103d98f
apply default base logic to BSI v1 migration code 2019-07-31 11:38:36 -05:00
Travis Turner
c5140ba88d
default BSI base value to min, max, or 0 depending on the min/max range 2019-07-31 09:19:04 -05:00
Travis Turner
a0560a0405
Merge pull request #2048 from travisturner/ingest-worker-pool
Add a worker pool for importRoaring jobs
2019-07-26 13:41:22 -05:00
Travis Turner
1af4219c62
Merge branch 'master' into ingest-worker-pool 2019-07-26 13:24:01 -05:00
Matthew Jaffee
c1f8216b3a
Merge pull request #2041 from pilosa/uip-time-only
use union in place when computing time ranges to avoid excessive allocation
2019-07-26 13:05:23 -05:00
seebs
e8bade6174
Merge branch 'master' into uip-time-only 2019-07-26 12:30:10 -05:00
Travis Turner
e044712675
add close() method to api 2019-07-26 11:34:29 -05:00
Seebs
1d732e4b7f drop unused functions from previous unmarshal implementation 2019-07-25 16:11:57 -05:00
Seebs
2d9ca0888f Use work queue for opening/closing fragments
When starting up, we can have a large number of views, each
with some number of fragments, and by default these were being
opened sequentially. There's no real benefit to that; they're
all nicely independent from each other and don't need much
locking, so we implement a trivial semaphore and launch the
operations asynchronously. We also combine them into
errgroups.

Similarly, we do this for fields and views, capping the number
of fields (or views) opened in parallel to avoid hitting a
system-wide limit on threads created (oops). Note that the
limits are shared, not multiplicative; we cap this fairly
arbitrarily at 8 fields being opened, and 16 views being opened,
at a time, but NumCPU*2 fragments being opened by those views.

This dramatically increases CPU load during startup, but doesn't
seem to significantly increase total CPU time, it just scales
much better on machines with lots of cores.
2019-07-25 16:03:24 -05:00
Seebs
b04037900c move to using roaring iterators for UnmarshalBinary
The new roaring iterator used for the remap and importroaring
things could also be used for unmarshalling roaring streams,
and it's a slightly simpler design that doesn't need two passes
through the data. This patch cleans that up a bit, makes it work
better with ops logs, and uses that instead. It appears to
noticably but not immensely reduce the time imports take, but it
also gets us back down to one thing parsing roaring formats.

There are a couple of subtle changes to errors we were testing
for in various tests, and one of the fuzz tests goes away because
it was actually itself an erroneous error message -- it was reporting
the header of a roaring file as an invalid op because the op log
reader was running on the header for roaring files with zero
containers. Oops.
2019-07-25 16:03:18 -05:00
Seebs
29a1db4550 add "holder" command to start up and shut down
It would be neat to be able to observe performance of
"just open the holder". So let's make that a verb.
2019-07-25 15:38:38 -05:00
Ashley Svetlik
e028640ba2
Merge pull request #2045 from asvetlik/pdk2
Updated PDK
2019-07-25 15:33:58 -05:00
Travis Turner
ea29759774
adds a worker pool for importRoaring jobs 2019-07-25 11:41:47 -05:00
Matt Jaffee
5b655418b1
add another single day query test 2019-07-25 08:12:19 -05:00
Matt Jaffee
2c311e685e
add bounds check when getting time rows 2019-07-25 08:12:19 -05:00
Seebs
ff153459ee
union many things at once to cut down allocations 2019-07-25 08:12:19 -05:00
Ashley Svetlik
ae4d86e69a
Merge branch 'master' into pdk2 2019-07-24 16:45:05 -05:00
Ashley Svetlik
7320eeac4d
Merge pull request #2046 from asvetlik/admin2
Updated Open File Limit in Administration Doc
2019-07-24 16:02:00 -05:00
Ashley Svetlik
e45d03687b Improved wording in text and table 2019-07-24 10:49:47 -05:00
Ashley Svetlik
6e6c591f62 Added max url links 2019-07-24 10:41:54 -05:00
Ashley Svetlik
27e62c40cf Improved Open File Limit section wording 2019-07-24 10:22:09 -05:00
Ashley Svetlik
be218fd963 Updated Open File Limit Section 2019-07-24 09:38:06 -05:00
Ashley Svetlik
6d58db4fc9 Updated Pilosa Schema table and added pdk repo link 2019-07-24 09:32:18 -05:00
Matthew Jaffee
bd00f1bfe2
Merge pull request #2034 from jaffee/worker-pool
Worker pool
2019-07-15 14:48:39 -05:00
Matt Jaffee
9a453ef51a
expose worker pool size to config, so we can set it lower in tests
we are experiencing issues with CI where it fails with race: limit on
8128 simultaneously alive goroutines is exceeded, dying

this, despite the fact that closing the executor should clean up all
worker goroutines. Apparently in CircleCI runtime.NumCPU() reports 36,
so the goroutines added up quickly.
2019-07-15 14:25:40 -05:00
Matt Jaffee
a7d9b0a5ae
make sure workers are done when closing via a WaitGroup
still running out of goroutines in race tests in CI, so hopefully this
fixes that.
2019-07-15 08:36:22 -05:00
Matt Jaffee
7d7a5539ca
make executor work chan smaller, add executor.Close
the size of the work chan probably doesn't matter... there is some
discussion of this on the associated PR
https://github.com/pilosa/pilosa/pull/2034
may test with an unbuffered channel as well.

Closing the executor avoids leaking goroutines which seems to be an
issue while running the test suite.
2019-07-15 07:56:57 -05:00
Matt Jaffee
4e55a1fd73
add worker pool to executor for local query processing
Pilosa previously spawned a goroutine for each remote node that a
query needed to be forwarded to, and then forwarded a single request
containing all the shards that the query should operate on. It then
spawned a goroutine *per local shard* to process the query
locally. This was fine if there weren't too many shards, or too many
queries coming in concurrently, but we found that it created issues
when there were 100s or 1000s of shards per node, and dozens of
queries arriving concurrently.

Specifically, the memberlist "hiccup" issue is highly correlated with
many goroutine scenarios, and after applying this patch, memberlist
complaints in the logs were much decreased, and nodeLeave events under
concurrent query load almost entirely eliminated.

This patch creates a fixed size pool of goroutines to do local shard
processing, and passes work to them through a channel, one job per
query per shard. Handling of remote requests (forwarding queries) is
unchanged.

We set the pool size to NumCPU()+8 somewhat arbitrarily, but this
seemed to work pretty well in our testing on 32 core machines. It's a
pretty big improvement over launching a goroutine per shard per query
which is what we were doing previously, so we can tune it more later
if necessary.
2019-07-12 17:16:48 -05:00
Matt Jaffee
ec09582f44
get read lock only where possible in Holder 2019-07-12 13:36:56 -05:00
Yuce Tekol
430b8a6118
Merge pull request #2033 from yuce/fixes-2009
Fixes #2009
2019-07-09 21:27:10 +03:00
Yuce Tekol
30036387cc
add remove at version 2.0 notices 2019-07-09 21:13:51 +03:00
Yuce Tekol
bc0098ccbe
Merge branch 'master' into fixes-2009 2019-07-09 21:11:43 +03:00
Yuce Tekol
6e6efc3d96
Merge pull request #2032 from yuce/fix-min-max-row-pb-result
fixes #2031
2019-07-09 16:50:07 +03:00
Yuce Tekol
d6bb5c65de
Fixes #2009 2019-07-09 16:41:18 +03:00
Yuce Tekol
150c2a0cfa
fixes #2031 2019-07-09 12:25:18 +03:00
asvetlik
c2cbaddba8
Merge pull request #2028 from asvetlik/master
Getting Started Update
2019-07-03 15:34:06 -05:00
asvetlik
42a1d851cb
Merge branch 'master' into master 2019-07-03 15:06:58 -05:00
Matthew Jaffee
8b2e257171
Merge pull request #2029 from jaffee/disable-tracing
add ability to disable tracing and use nopTracer
2019-07-03 15:02:54 -05:00
Ashley Svetlik
c6e840ea30 Fixed jq note link 2019-07-03 14:12:11 -05:00
Ashley Svetlik
2db061ac21 Reformatted Schema Check 2019-07-03 14:02:00 -05:00
Ashley Svetlik
daad23b388 Made review chnages 2019-07-03 13:52:18 -05:00
Matt Jaffee
efd424ebab
add ability to disable tracing and use nopTracer
Have found some potential performance or stability issues associated
with lots of mutex blocking in getting a parent span's context. Want
the ability to totally disable tracing to help debugging.
2019-07-03 11:02:59 -05:00
Ashley Svetlik
614bcff1e0 Deleted redundant paragraph in Sample Project 2019-07-03 08:12:58 -05:00
Ashley Svetlik
e38983782c Fixed Schema check note 2019-07-02 15:35:07 -05:00
Ashley Svetlik
f991df206c Made Schema check into note 2019-07-02 15:24:56 -05:00
Ashley Svetlik
36c75ea416 Removed Note before schema check 2019-07-02 15:21:16 -05:00
Ashley Svetlik
f40958fd5a Improved documentation wording 2019-07-02 11:27:27 -05:00
Ashley Svetlik
636c7d2966 Made syntax, format, and wording corrections 2019-07-01 16:42:46 -05:00
Matthew Jaffee
9df46353e7
Merge pull request #2024 from seebs/unmarshal3
Unmarshal3
2019-07-01 14:39:40 -05:00
Seebs
0960d66c94
update diagnostic message, use read locks for read
Annoyingly, this is actually the only place we can make
a read-only lock, because the row() call might write to
the row cache, so it needs the write lock. We might be
able to fix that later, though.
2019-07-01 13:16:03 -05:00
Seebs
e1fbed51b2
use symbolic names for op types, add checks for invalid types 2019-07-01 13:16:03 -05:00
Seebs
b74956e48e
drop no-longer-used timeout case 2019-07-01 13:16:02 -05:00
Seebs
17eb13702e
address lint concerns
Addressing various lint.

incrementOpN no longer returns errors, because it no longer waits for
the snapshot, so checking those errors is unnecessary.

Several fields in a common embedded structure were "unused" according
to a naive checker.

Other tiny style things, and one actual unchecked error. Yay linters!
2019-07-01 13:16:02 -05:00
Seebs
5e3d01febe
lock fragment to compute rows
If you don't hold the fragment lock when computing rows, it's
pretty reasonable for other stuff to be able to modify it -- which
could invalidate or race the enumeration.

Some calls to f.rows were being made with the lock held, others
weren't, so we introduce `f.unprotectedRows` which has the obvious
semantics. (Without which this looked great except that several
of the tests deadlocked.)
2019-07-01 13:16:02 -05:00
Seebs
cb50a5a48b
revert BSIv2 change impact on Official Roaring
The Pilosa roaring format uses two bytes of its
header, next to the magic number, for a version. The
official roaring format uses them for a container
count, if and only if it's the version of the format
that uses run-length containers.

But if it is, it really does need those bits. Also,
since we never use the official format in our internals
or snapshots, we don't have any reason to support
reading flag bits in it, since the flag bits are used
only for internals of fragments and snapshots. So
we revert the change to support flags with official
roaring bitmaps.

A couple of the fuzz tests happened to rely on this,
and we may find more issues with more fuzzing.
2019-07-01 13:16:02 -05:00
Seebs
67830b74cf
allow importRoaring to work with official format roaring
I didn't think of this, because we don't use it much in the
client. This is a bit hairy because really official roaring
is two fairly different formats, one with runs and one without.
2019-07-01 13:16:02 -05:00
Seebs
4b657c1962
use a queue for snapshot operations
As the size of a fragment grows, the cost of snapshots
increases; with a large fragment getting a lot of large writes,
every write will trigger a snapshot, while any other writes have
to wait for that snapshot before they, too, can trigger a snapshot.

To address this, we introduce a background queue of snapshots.
In general, operations which were omitting their ops log writes
and just snapshotting no longer do; they emit an ops log. This does
mean that, in some cases, the ops log is written and then a snapshot
takes place essentially immediately, which costs us some performance.
However, that only actually happens under very light load; under
heavier load, there's generally going to be multiple writes coalesced
into each snapshot, and the ops log writes for them will be much
cheaper than a full snapshot.
2019-07-01 13:16:02 -05:00
Seebs
b369dace69
remap storage on reopen, instead of remarshalling it
When we do a snapshot, we may end up with containers which are
mmapped to the old file, and containers which have allocated storage
identical to the contents of the new file. It would be nicer if they
were mapped to it. But unmarshalling the entire file is expensive.

Instead, we remap it. (Or, if we couldn't mmap it, just make sure
the old stuff is no longer using the old storage space before we
munmap it.)
2019-07-01 13:16:02 -05:00
Seebs
565288f6c2
use ImportRoaringBits to implement importRoaring
Instead of fancy bitmap ops or ImportPositions, we use the
recently-added ImportRoaringBits operations, which can dump
themselves to op logs much more efficiently, and which are
also usually much more efficient than things like "create a
new bitmap which is a copy of the old one".
2019-07-01 13:16:02 -05:00
Seebs
7f1763e466
address fuzz testing for new op types
The new op type code changed the failure mode for
one of the fuzz test issues -- and the fuzz test revealed a
bug in the code. Fixed the code, updated the test to expect
the newer, better, message.

Also fixed capitalization on the old message.
2019-07-01 13:16:01 -05:00
Seebs
c19b7af0d0
Support direct roaring import operations
We add a new ops log type(pair), AddRoaring and RemoveRoaring,
which set and clear the bits from a provided roaring bitmap.

This also compels us to consider additional sanity checking
during tests.
2019-07-01 13:16:01 -05:00
Seebs
4d1e9ed78a
reshuffle benchmarks and include cache type in testing
It turns out there's some significant potential improvements to
be had in the case where there's no cache being used on a field, so
we add it to the benchmarks, to allow testing that.

We also make sure that `getUpdataInto` picks the requested number
of columns; if N was a point at which something weird happens,
we might only sometimes see it.
2019-07-01 13:16:01 -05:00
Ashley Svetlik
c8e68c8456 Revised to include review comments 2019-07-01 08:43:22 -05:00
Ashley Svetlik
9d7273e061 Added the Sample Project subsections to left nav area 2019-06-28 12:39:14 -05:00
Ashley Svetlik
680b0119a9 Added explanation and fixed typos 2019-06-28 11:44:52 -05:00
Ashley Svetlik
74cfa79bb0 Added Python 2019-06-27 16:06:18 -05:00
Ashley Svetlik
93da23d902 Added Java and Fixed Typos 2019-06-27 10:17:50 -05:00
seebs
72c6867220
Merge pull request #2026 from seebs/viewRace
view.deleteFragment should hold the lock while altering fragments
2019-06-26 22:01:58 -05:00
Ashley Svetlik
66867b0cb8 Fixed typos 2019-06-26 16:31:24 -05:00
Seebs
b2fb51be1f view.deleteFragment should hold the lock while altering fragments
If you delete a fragment while something else is calling allFragments,
you can cause a race. This almost never happens in practice, because
deleting fragments is rare, and the only likely overlap would be with
something like the holder cache flush, which only happens once a
minute. But if you slowed down the rest of the tests enough, and ran
with -race, you might see it.

We check v.fragments directly instead of calling v.Fragment, because
v.Fragment also needs a lock, and we don't want to drop the lock between
the check for existence and the delete operation.
2019-06-26 16:14:37 -05:00
Ashley Svetlik
7e9fed87e7 Reformatted and added HTTP 2019-06-26 16:04:17 -05:00
asvetlik
03cb21afbd
Merge pull request #2016 from asvetlik/tests
Test for no containers
2019-06-26 10:48:32 -05:00
asvetlik
f54bb5ed2b
Merge branch 'master' into tests 2019-06-26 10:07:20 -05:00
Shaquille Wyan Que
8ea314ac5e
Merge pull request #2023 from shaqque/fuzz-roaring
Add naive implementations of Roaring and fuzz test
2019-06-26 10:07:03 -05:00
asvetlik
91387ba601
Merge branch 'master' into tests 2019-06-26 09:31:37 -05:00
shaqque
368bb46f45 switched naive_test.go to table driven tests 2019-06-25 17:25:07 -05:00
Ashley Svetlik
4b0962bb17 Merge branch 'master' of https://github.com/asvetlik/pilosa 2019-06-25 13:35:56 -05:00
Ashley Svetlik
59e94b451c Removed pilosa import and added go 2019-06-25 13:34:54 -05:00
shaqque
7ba9e18a51 Merge branch 'master' of https://github.com/pilosa/pilosa into fuzz-roaring 2019-06-25 11:22:47 -05:00
shaqque
bc0f86755a added roaringsentinel build tag to check for user errors at build time 2019-06-25 11:16:34 -05:00
asvetlik
8fd603637b
Merge pull request #2021 from asvetlik/master
Malformed Offset Bug in readOffsets and readWithRuns
2019-06-25 10:52:21 -05:00
shaqque
4f8b3f650e added go-fuzz testing for roaring ops vs naive implementation 2019-06-25 10:47:53 -05:00
asvetlik
fb841c3327
Merge branch 'master' into master 2019-06-25 08:10:40 -05:00
Shaquille Wyan Que
8760ed77b2
Merge pull request #2019 from shaqque/2015RoaringBugs
Fix various container iteration bugs in Roaring
2019-06-24 22:03:33 -05:00
Shaquille Wyan Que
46121da00a
Merge branch 'master' into 2015RoaringBugs 2019-06-24 21:33:57 -05:00
shaqque
86e703637b fixed seeking end of run container iteration bug when next container exists and ensure roaringparanoia panics before other ops 2019-06-24 15:18:03 -05:00
Ashley Svetlik
f137f00fe3 Merge branch 'master' of https://github.com/asvetlik/pilosa 2019-06-24 13:05:34 -05:00
Ashley Svetlik
db90b798d7 Merge branch 'master' of https://github.com/asvetlik/pilosa 2019-06-24 13:00:30 -05:00
asvetlik
998e89d9d6
Merge pull request #2 from asvetlik/revert-1-master
Revert "Merge pull request #2017 from asvetlik/master"
2019-06-24 12:59:47 -05:00
asvetlik
3a96315a28
Revert "Merge pull request #2017 from asvetlik/master" 2019-06-24 12:59:31 -05:00
asvetlik
3910c6d08f
Merge pull request #1 from pilosa/master
Merge pull request #2017 from asvetlik/master
2019-06-24 12:57:34 -05:00
Ashley Svetlik
55aa864cac Fixed malformed offset bug in readOffsets 2019-06-24 12:55:32 -05:00
Ashley Svetlik
eb5d1ae1a4 Fixed malformed offset bug in readWithRuns 2019-06-24 12:51:10 -05:00
asvetlik
464cc1d4ed
Merge branch 'master' into tests 2019-06-24 12:31:14 -05:00
asvetlik
b70986bcdb
Merge pull request #2017 from asvetlik/master
Malformed bitmap in pilosa fix
2019-06-24 12:31:00 -05:00
Ashley Svetlik
b0165d7ef9 Revised WithErrors test with err corrections 2019-06-24 12:22:51 -05:00
asvetlik
9c5848daeb
Merge branch 'master' into master 2019-06-24 12:13:52 -05:00
Ashley Svetlik
6b6249b86a Merge branch 'tests' of https://github.com/asvetlik/pilosa into tests 2019-06-24 12:13:06 -05:00
Ashley Svetlik
7ff26194d8 Corrected err and checked for err 2019-06-24 12:11:44 -05:00
asvetlik
250a3f6fbb
Merge branch 'master' into tests 2019-06-24 09:02:52 -05:00
Matthew Jaffee
ab6bed1187
Merge pull request #2020 from jaffee/extra-nodeleave-log
more info if nodeleave confirmation queries fail
2019-06-21 14:53:53 -05:00
Matt Jaffee
c0d067b7ee
move context timeout inside loop, so context gets a fresh deadline 2019-06-21 12:15:58 -05:00
Ashley Svetlik
8fd23239a1 Formatted Fuzz_test.go 2019-06-21 10:09:20 -05:00
Shaquille Wyan Que
a6ba7e339c fix container iteration bugs in roaring 2019-06-20 20:50:58 -05:00
Matt Jaffee
481c85acae
more info if nodeleave confirmation queries fail 2019-06-20 17:32:57 -05:00
Ashley Svetlik
031e23cdea Resolved int overflow 2019-06-20 15:02:18 -05:00
Ashley Svetlik
157e910103 Fuzz_test changes 2019-06-20 14:49:04 -05:00
Ashley Svetlik
873486bc1a Removed no containers pilosa format fix 2019-06-20 14:43:55 -05:00
Ashley Svetlik
18d86a204c Revised test for pilosa roaring no containers 2019-06-20 14:36:38 -05:00
Ashley Svetlik
6943b3c5ba Returned files to original version 2019-06-20 14:35:35 -05:00
Ashley Svetlik
f6d2276a26 Edited openStorage() to make tsts pass 2019-06-19 16:56:49 -05:00
Ashley Svetlik
c8de8b1e21 Returned TestFragment_ClearRow to original 2019-06-19 16:37:26 -05:00
Ashley Svetlik
76b059c48e Got TestFragment_ClearRow() to succeed 2019-06-19 16:17:51 -05:00
asvetlik
f772ca4a34
Merge branch 'master' into master 2019-06-19 14:48:48 -05:00
Ashley Svetlik
ea4950781a Changed roaringData/roaringFileName and made tests work 2019-06-19 14:09:06 -05:00
Ashley Svetlik
cf900e03f9 changed testLoop/testValues and rearranged for loop 2019-06-19 13:54:39 -05:00
Ashley Svetlik
2df44eecfd Implemented previous fixes not present 2019-06-19 13:38:23 -05:00
Ashley Svetlik
656efb4ea6 Fixed fuzz_test.go order to mergability 2019-06-19 13:08:54 -05:00
Ashley Svetlik
8c264d9249 Resolved offical roaring no containers error 2019-06-19 12:59:36 -05:00
Ashley Svetlik
42b2d0787b Merge branch 'iss#2005' 2019-06-19 12:48:05 -05:00
asvetlik
fe83ef59c7
Merge pull request #2012 from asvetlik/iss#2005
Added a test code to test the fuzzer bugs and fixed 2 of the bugs found in roaring
2019-06-19 12:47:24 -05:00
asvetlik
a9edf40a5b
Merge branch 'master' into iss#2005 2019-06-19 12:25:23 -05:00
asvetlik
7aa2211a6d
Merge pull request #2004 from asvetlik/master
Added fuzzing code and readme.md to explain the fuzzer
2019-06-19 12:24:50 -05:00
asvetlik
ff46818072
Merge branch 'master' into master 2019-06-19 12:07:16 -05:00
Ashley Svetlik
453c29a465 Fixed a malformed bitmap bug in pilosa roaring 2019-06-19 11:38:20 -05:00
Ashley Svetlik
3eed3b472f Corrected If statement logic error 2019-06-19 10:36:04 -05:00
Ashley Svetlik
2d151cd41a Making CI happy 2019-06-18 16:48:03 -05:00
Ashley Svetlik
97f525ff06 Removed fuzz_test.go 2019-06-18 16:40:10 -05:00
Ashley Svetlik
8445f6bdef Test for no containers in pilosa roaring and fixed 2019-06-18 11:05:30 -05:00
Ashley Svetlik
cae1a76629 Fixed typo 2019-06-17 16:47:28 -05:00
Ashley Svetlik
ba05ef659b Organized TestUnmarshalRoaringWithNoErrors and created TestUnmarshalRoaringWithErrors 2019-06-17 16:36:05 -05:00
Ashley Svetlik
d24a157947 Addressed review feedback 2019-06-17 15:58:20 -05:00
Yuce Tekol
284aac6c7d
Merge pull request #1983 from yuce/min-max-rowid
Add MinRow and MaxRow calls
2019-06-17 22:57:15 +03:00
Yuce Tekol
dec665ac75
Merge branch 'master' into min-max-rowid 2019-06-17 22:44:33 +03:00
Ashley Svetlik
d9f2792d1f Reworded max int error and reset max int value 2019-06-17 14:11:37 -05:00
Ashley Svetlik
81f8d80fe1 Provided example on how to copy Pilosa fragments in README.md 2019-06-17 08:40:31 -05:00
Ashley Svetlik
413492552c Rearranged if statement and declared maxOpSize value 2019-06-17 08:36:56 -05:00
Yuce Tekol
5c59449ed2
reset roaring.go and added bitmap.Min 2019-06-17 16:12:43 +03:00
Yuce Tekol
06aa2cf98e
updated for feedback from PR 1983 2019-06-15 15:15:20 +03:00
Ashley Svetlik
734daf79ee Simplified the if statement and made the calculation more precise 2019-06-14 14:30:21 -05:00
Ashley Svetlik
77cb1ea6d8 Claified the arithmetic behind the max op.value 2019-06-14 13:44:04 -05:00
Ashley Svetlik
56659f9d7b Added Licensing 2019-06-14 11:47:33 -05:00
Ashley Svetlik
f4157efcb9 Added Licensing 2019-06-14 11:46:13 -05:00
Ashley Svetlik
a00ef2760b Added Licensing 2019-06-14 11:11:53 -05:00
Ashley Svetlik
3f4543cfb4 Merge branch 'master' of https://github.com/asvetlik/pilosa 2019-06-14 10:52:46 -05:00
Ashley Svetlik
7182de5f30 Added -bin -workdir and -func flags to README.md 2019-06-14 10:41:31 -05:00
asvetlik
b0f4b8b94e
Merge branch 'master' into master 2019-06-14 10:21:14 -05:00
asvetlik
cbc7aa2dda
Merge branch 'master' into iss#2005 2019-06-14 10:20:23 -05:00
Ashley Svetlik
1e7638677b Fixed the :000000 bug by adding an = in readOfficalHeader 2019-06-14 10:08:23 -05:00
Ashley Svetlik
622fba4f27 Fixed the <000000000 bug by adding if statement 2019-06-14 10:06:37 -05:00
Ashley Svetlik
0a87d8108f Added the actual bytes and their respective errors 2019-06-14 10:05:06 -05:00
Ashley Svetlik
a1f6321b1d Added a test for slice bounds out of range 2019-06-13 11:54:52 -05:00
Ashley Svetlik
4039583ccd Added fuzzing code and readme.md to explain 2019-06-13 11:11:47 -05:00
Cody Soyland
8a278b8ae7
Merge pull request #2001 from codysoyland/docker-alpine-update
Update Alpine to 3.9.4 in Dockerfile
2019-06-13 10:47:49 -05:00
Cody Soyland
616cba0cd8
Merge branch 'master' into docker-alpine-update 2019-06-13 10:39:31 -05:00
Yuce Tekol
739926da52
Merge pull request #2000 from yuce/fix-1982
Updated with atomic writes
2019-06-13 17:58:02 +03:00
Cody Soyland
6746a54e01 Update Alpine to 3.9.4 in Dockerfile 2019-06-13 09:32:14 -05:00
Yuce Tekol
28f56b8c97
Merge branch 'master' into min-max-rowid 2019-06-12 17:14:34 +03:00
Yuce Tekol
e7e5e21acd
trivial 2019-06-12 17:07:23 +03:00
Yuce Tekol
c9854c00fb
updated with atomic writes 2019-06-12 16:46:18 +03:00
seebs
fe590d4265
Merge pull request #1997 from seebs/slicefix
handle insertions correctly
2019-06-11 09:39:19 -05:00
Yuce Tekol
2b91277155
Merged with master 2019-06-11 16:59:59 +03:00
Yuce Tekol
13a42d9c07
replaced min code with bmp.iterator 2019-06-11 16:58:32 +03:00
Seebs
089e7e127e handle insertions correctly
The "Update" case for Slice containers is broken, and can
insert a container without inserting a key. Fix this by using
the existing insert/add logic.
2019-06-10 15:22:38 -05:00
Cody Soyland
bbb5766bc0
Merge pull request #1996 from codysoyland/stats-reduce
Remove extraneous stat tags to improve prometheus performance
2019-06-10 10:11:42 -05:00
Cody Soyland
39c5ecee38
Merge branch 'master' into stats-reduce 2019-06-10 09:35:07 -05:00
Cody Soyland
40dfffc833
Merge pull request #1994 from codysoyland/prometheus
Add Prometheus tests, refactor http stats as middleware, minor fixes
2019-06-10 09:34:50 -05:00
Cody Soyland
726b001b91
Merge branch 'master' into prometheus 2019-06-10 09:16:09 -05:00
Cody Soyland
db1587e4c8 Fix tests 2019-06-10 09:15:37 -05:00
Cody Soyland
9fb6d84d80 Remove extraneous stat tags to improve prometheus performance 2019-06-10 08:18:30 -05:00
Ben Johnson
bc98d5418e
Allow partial translate file reads. (#1987)
Allow partial translate file reads.
2019-06-07 15:43:44 -06:00
Ben Johnson
815005d461
Merge branch 'master' into allow-translate-key-small-buffer 2019-06-07 14:51:10 -06:00
Cody Soyland
430becdd3f Add tests for prometheus stats client 2019-06-07 09:58:40 -05:00
Cody Soyland
363a19b321 Add request method to stats 2019-06-07 09:20:40 -05:00
Cody Soyland
da04eb7bc3 Use timing instead of histogram for http requests 2019-06-07 09:13:38 -05:00
Cody Soyland
04b5d4b79b Use seconds, not milliseconds for timings 2019-06-07 09:13:38 -05:00
Cody Soyland
e8dd61d359 Refactor stats collector to middleware, tag path instead of full url 2019-06-07 09:13:37 -05:00
Cody Soyland
2d6e948c83 Return after errors 2019-06-07 09:13:37 -05:00
Matthew Jaffee
edd26407f5
Merge pull request #1992 from codysoyland/prometheus
Add Prometheus stats backend
2019-06-05 21:40:43 -05:00
Cody Soyland
fc33f7ea66
Add errantly removed pathParts definition 2019-06-05 21:23:12 -05:00
Cody Soyland
14920758aa
Add docs pertaining to prometheus 2019-06-05 21:23:12 -05:00
Cody Soyland
97e1822445
Remove urls from stat names, instead tag http.request stats with url 2019-06-05 21:23:11 -05:00
Cody Soyland
2de8060f2c
Use prometheus-compatible metric naming 2019-06-05 21:23:11 -05:00
Cody Soyland
d3db48a1fd
Add missing fields 2019-06-05 21:23:11 -05:00
Cody Soyland
68e89c63f8
Implement prometheus timing 2019-06-05 21:23:11 -05:00
Cody Soyland
c5ce27d7ef
Implement histogram/observer/summary stats 2019-06-05 21:23:11 -05:00
Cody Soyland
dfc7cfa4aa
Fix linter errors and add gauge support to prometheus 2019-06-05 21:23:11 -05:00
Cody Soyland
4c7aa4af81
Add Prometheus stats client with Count support 2019-06-05 21:23:11 -05:00
Cody Soyland
8fb8f1d8f7
go mod fix + tidy 2019-06-05 21:23:11 -05:00
Cody Soyland
7e4c3b715b
Add basic prometheus support 2019-06-05 21:23:10 -05:00
tgruben
00c01ab2d6
Merge pull request #1993 from tgruben/confirm-fail
False Positive nodeLeave events put cluster in an unusable state (Starting)
2019-06-05 20:16:40 -05:00
Todd Gruben
0b392164cc Stabilization Time not long enough for new cluster test 2019-06-05 18:48:35 -05:00
Todd Gruben
b9ab21dfd2 Decreased the number of retries for dead node confirmation 2019-06-05 15:13:53 -05:00
Todd Gruben
e4dbafd03e Duplicate log entry 2019-06-05 14:58:35 -05:00
Todd Gruben
5ddbe0b51a Merge branch 'confirm-fail' of github.com:tgruben/pilosa into confirm-fail 2019-06-05 14:54:08 -05:00
Todd Gruben
c99071d5bf timeout handleded incorrectly;added tests 2019-06-05 14:53:35 -05:00
tgruben
2376a2bcec
Merge branch 'master' into confirm-fail 2019-06-05 11:42:10 -05:00
Todd Gruben
085e29543e False Positive nodeLeave events put cluster in an unusable state 2019-06-05 11:28:41 -05:00
seebs
aa5c5a3afa
Merge pull request #1990 from seebs/renameSemantics
use os.Rename semantically correctly
2019-06-04 11:50:05 -05:00
Ben Johnson
7ff684c193
Allow partial translate file reads.
This commit fixes an issue where translation `LogEntry` must be
read in its entirety, however, large entries can exceed the buffer
size. This has been changed so that partial entries reads are allowed.

The `LogEntry.ReadFrom()` may still generate large byte slices
during reads of large individual fields or keys.
2019-06-04 10:08:52 -06:00
Seebs
388efd0e73 use os.Rename semantically correctly
So it's true that Rename's arguments are called oldname/newname, and
you want to rename from the previous name to the new name.

And it's true that we're calling Rename on oldPath and newPath.

But in our case, oldPath is the name the fragment file had before
the operation, and newPath is the name of the temporary file
created during the operation. Use tmpPath and frag.path to make
the semantics clearer.
2019-06-04 10:00:16 -05:00
seebs
83ec03a245
Merge pull request #1989 from seebs/rowcacheFix
Rowcache fixes
2019-06-04 09:28:48 -05:00
Seebs
77cd21e89f don't check errors we don't care about in a test 2019-06-04 09:16:01 -05:00
Seebs
372c369e7c Optimize needs to use the new container logic
When calling `.optimize`, need to grab the new container which
may be different from the original container.
2019-06-04 08:56:56 -05:00
Yuce Tekol
b64a3e0c68
adds filter support to MinRow and MaxRow 2019-06-03 16:29:04 +03:00
Yuce Tekol
3e738e9760
Merge branch 'master' into min-max-rowid 2019-06-03 14:10:51 +03:00
Yuce Tekol
8be7bd6956
add tests for MinRow and MaxRow 2019-06-03 13:56:50 +03:00
Seebs
973579e662 on freeze, unmap mapped containers
It turns out that calling syscall.Munmap() is a thing which
can change any container holding a pointer into the mapped space,
but which wouldn't detect frozen containers. So we need to
copy storage for such things. This negates some of the memory
wins of the rowcache code, but makes it not crashy.
2019-05-31 16:17:06 -05:00
Seebs
636f132564 add a test case which breaks the rowcache code
It turns out that frozen containers which have mmapped data are
only safe *until the data gets unmapped*. Which it does on a snapshot.
2019-05-31 16:16:51 -05:00
Matthew Jaffee
f09c3ebf7c
Merge pull request #1986 from jaffee/1985-flags-unmarshal
fixed swapped order of flags and file version bytes on unmarshal
2019-05-31 10:20:40 -05:00
Yuce Tekol
1379cbbcd6
remove unused code 2019-05-31 17:35:50 +03:00
Yuce Tekol
592a191aee
translate key into Pair only for MinRow, MaxRow 2019-05-31 17:21:44 +03:00
Matt Jaffee
1515ddaf14
fixed swapped order of flags and file version bytes on unmarshal
also fix tests to use correct flags for bsi fields
2019-05-31 09:18:05 -05:00
Yuce Tekol
08f4ccb29b
Fixed conflicts; Merged with master 2019-05-31 17:16:54 +03:00
Yuce Tekol
dd728f28ed
remove unused code 2019-05-31 17:13:25 +03:00
Yuce Tekol
d2aca3bbfc
Added MinRow and MaxRow calls 2019-05-31 15:32:15 +03:00
seebs
dfbb666f9d
Merge pull request #1974 from seebs/rowcache3
WIP: Improve row cache (mostly by not doing it)
2019-05-30 16:57:49 -05:00
Seebs
c133ce0376 Make containers copy-on-write
This patch replaces a lot of circumstances in which containers
were being copied with circumstances in which they are shared,
using copy-on-write semantics.

To achieve this, we emulate somewhat the design of go's
native `append` function. Operations on a container may optionally
yield a new container. A container can be marked "frozen",
after which no operation should ever write to it in any way;
that applies both to the container itself and the backing store
it refers to, if any. So for instance, instead of:

	c.arrayToBitmap()

we now write:

	c = c.arrayToBitmap()

Operations which need to modify a container in any way
need to be able to return a new container, which is a modified
copy of the previous container. This applies to operations
like add/remove, but also to things like unmapping memory-mapped
storage, or changing a container's type.

Bitmaps do not support the same copy-on-write semantics,
currently, but "copying" a bitmap and sharing the containers
instead of duplicating them is *much* cheaper than copying
the containers.

Bitmaps do support a .Freeze method, which currently copies
the previous bitmap, making a new one with the same container
pointers, and freezes the individual containers. Use this
if you need a writeable copy of a bitmap -- the resulting
bitmap can safely have its set of containers modified, and
bitmap operators that would want to modify the containers
will use copy-on-write for that.

The primary motivation of this is to reduce the cost of the
row cache used by fragments. As a secondary issue, the row cache
is no longer updated on writes -- that update was actually a
race condition waiting to happen. Rather, writes to a row
invalidate the cache entry for that row. The row cache is
created by creating a new bitmap, and freezing the relevant
containers from the fragment's storage. In the case where
nothing is being written, the row cache grows to contain
bitmaps containing all those containers, but never copies
any containers. If nothing's being read, the row cache is
never created, and the containers are in general not getting
frozen. The only circumstance where copies have to happen is
when things are read (and thus stored in the row cache) and
later modified. In that case, each read freezes objects, and
the first write to a container after it's been frozen will
create a new copy.

We drop the enterprise/b btree implementation, because we
don't really need it anymore -- we now provide that
implementation by default in the open source product anyway.

Along with this, there's a lot of other changes which
improve support for nil containers, as a cheaper representation
for empty containers. Operations which we know will provide
an empty container can always short-circuit and just yield
a nil *Container. Similarly, operations which would provide
a full container can return a single shared full container
object (which is frozen). The higher-level (non type-specific)
container ops are now using that logic to short-circuit
operations for empty and full containers. (For instance,
difference of anything minus an empty container is the
original thing, union of anything and empty is the original
thing, and so on.)

The Containers interface adds "Update" and "UpdateEvery"
methods, based in part on the "Put" interface provided
by the underlying btree implementation; Update performs
a possible update in-place of a container for a given
key, bypassing the need to replicate the search for that
key in the container. UpdateEvery loops through all the
containers.

Containers do not strictly guarantee that they won't
return nil `*Container` objects. However, the container
iterators won't return those -- empty containers aren't
interesting. Some tests are updated to reflect this.

Some of the container internals, like N(), or the isArray()
and related functions, accept nil container pointers. Some,
like Thaw(), do not. For the array(), bitmap(), and runs()
methods, roaringparanoia enables an explicit panic on a nil
container explaining the problem, but the intent is that those
should never be called unless you already know you have the
right kind of container, so by default they don't perform
the extra checks. In most cases, this is already covered
because a nil container is empty, and there's no operation
we can perform that requires us to inspect the contents of
an empty container. This is passing a fair amount of testing,
but the testing may not be comprehensive enough.

The overall impact of this is pretty trivial performance-wise.
In our default roaring/ benchmarks, a few things get a few
percent faster, or slower. The advantage is that, with
read-heavy workloads, the row cache no longer eats up incredible
amounts of memory.

For a smallish test case, pilosa's memory usage (RES in top) after
startup was ~2.5GB. Without this patch, simply reading every
row a few times got memory usage to about 9GB, which seemed
reasonably stable. With this patch, memory usage went to about
3GB. This will be less noticeable in mixed read/write loads,
but it should be consistently significantly lower.

In addition to dropping things from the rowCache on modifications,
we also stopped performing a full count on a modified row when
not using a cache of a kind that would use that count, and don't
repopulate the rowCache regardless. We don't want every write
to imply a corresponding read after it.

There's a lot of room for possible future optimizations in
terms of things like in-place operations, and some of the
row/rowSegment code is a little suspicious to me, but I don't
think it should be *worse* in any cases.
2019-05-30 16:36:20 -05:00
Seebs
63120e3715 rename slice containers source file descriptively
The containers.go file contains one of two Containers implementations,
it should have a name reflecting this.
2019-05-30 16:36:20 -05:00
Seebs
c587dbc94d drop enterprise/b
We added the containers_btree implementation to roaring/, which
makes it silly to keep this one. Also, this one is the only reason
that container.Mapped needed to be exported.
2019-05-30 16:36:20 -05:00
Yuce Tekol
778ae1e8e2
added enterprise btree first 2019-05-30 15:20:04 +03:00
Yuce Tekol
f15cb9e05c
added roaring min 2019-05-30 15:15:08 +03:00
Yuce Tekol
8706dd990f
Merge pull request #1980 from yuce/1977-fix-int-field-min-max
1977 fix int field min max
2019-05-29 10:08:24 +03:00
Yuce Tekol
c8a3dc8c18
fix int min max test for 32bit 2019-05-28 14:25:46 +03:00
Yuce Tekol
5e102154ca
make linter happy 2019-05-28 14:12:04 +03:00
Yuce Tekol
5f4c5d4d35
added test for 1977 fix 2019-05-28 13:54:12 +03:00
Yuce Tekol
b5e4b90438
fixes #1977 2019-05-27 17:43:53 +03:00
Yuce Tekol
62e2b16b88
set defaults for int field min and max 2019-05-27 15:49:10 +03:00
Ben Johnson
5612a827ab
Merge pull request #1978 from benbjohnson/topn-errors
Improve TopN() errors
2019-05-25 19:59:01 -06:00
Ben Johnson
dd4227f5e3
Improve TopN() errors
This commit improves field not found, integer field, and cache errors
for the `TopN()` command.
2019-05-25 15:16:45 -06:00
Ben Johnson
f59b49e4bb
Merge pull request #1902 from benbjohnson/unbounded-bsi-sigbit
Unbounded BSI w/ sign magnitude
2019-05-19 21:29:34 -06:00
Ben Johnson
40803372dd
Add min/max constraints; fix tests 2019-05-19 16:05:22 -06:00
Ben Johnson
d4de122549
Add min/max constraints 2019-05-17 15:52:17 -06:00
Ben Johnson
7ed9fba335
Unbounded BSI w/ sign magnitude
This commit implements BSI with variable bit depth using a
sign magnitudeto indicate whether a value is positive or negative.
This also rearranges the existence bit to be the first bit instead
of the last bit.
2019-05-17 15:52:17 -06:00
Shaquille Wyan Que
29e6bd29d7
Merge pull request #1975 from hackskills/1971-out-of-bounds
Fixed out of bounds panic to show error
2019-05-15 12:39:41 -05:00
Shaquille Wyan Que
44088d4f29 added check for unexpected parser error 2019-05-15 12:11:55 -05:00
Shaquille Wyan Que
6ba6218ae4 changed out of range error message name and fixed formatting 2019-05-15 11:22:04 -05:00
Shaquille Wyan Que
b770167db6 fixed formatting 2019-05-15 10:52:15 -05:00
Shaquille Wyan Que
98a864634e fixed out of bounds panic to show error 2019-05-14 16:58:03 -05:00
Shaquille Wyan Que
5f22aa3765
Merge pull request #1973 from hackskills/master
Fixed error message returned by regex on field and index names
2019-05-14 12:12:03 -05:00
Shaquille Wyan Que
fb93f90f31 fixed error message returned by regex on field and index names 2019-05-14 11:57:07 -05:00
Matthew Jaffee
6d26e69cf0
Merge pull request #1970 from jaffee/1967-groupby-filter-strings
Fix filter calls in GroupBy not being translated
2019-05-13 16:10:27 -05:00
Matt Jaffee
e185a01e67
add translation for groupby filter arg, improve test 2019-05-10 14:15:06 -05:00
Matt Jaffee
de61d04172
failing test for group by with filter using string keys
also, apparently our API code was assuming that imports with keys
always had timestamps which seemed wrong, so I fixed that.
2019-05-10 13:55:21 -05:00
Matthew Jaffee
d7d52d6b4e
Merge pull request #1954 from kuba--/reopen
TranslateFile - reopen the same instance
2019-05-06 10:41:43 -07:00
Matthew Jaffee
a74ca1ea3e
Merge branch 'master' into reopen 2019-05-03 13:42:33 -05:00
Matthew Jaffee
88634cbee8
Merge pull request #1966 from jaffee/update-contributing-guide
simplify contributing instructions by removing weird upstream thing
2019-05-03 10:34:14 -05:00
Matthew Jaffee
85e5c885cf
Merge branch 'master' into update-contributing-guide 2019-05-03 09:26:23 -05:00
Kuba Podgórski
42c62187cf
Merge branch 'master' into reopen 2019-05-03 01:11:15 +02:00
Matthew Jaffee
67d53f6b48
Merge pull request #1939 from jaffee/extra-tracing
Extra tracing
2019-05-02 12:16:25 -05:00
Kuba Podgórski
97e7f86372
Merge branch 'master' into reopen 2019-05-02 14:07:25 +02:00
kuba--
51ac675e82
TranslateFile - reopen the same instance
Signed-off-by: kuba-- <kuba@sourced.tech>
2019-05-02 14:05:40 +02:00
Matt Jaffee
27fab06e78
simplify contributing instructions by removing weird upstream thing
we can probably remove GOPATH too, but I'll save that for another day.

For now, we make it so that the obvious thing (cloning the official
repo) works as a normal part of the contribution process.
2019-05-01 17:37:52 -05:00
Matt Jaffee
00911d024b
add span around fragment lock, bytes written metadata 2019-04-30 16:55:46 -05:00
Matt Jaffee
61bf3d929d
Add more tracing and metdata to importRoaring 2019-04-30 15:49:52 -05:00
Travis Turner
e1e0d0cdfa
Merge pull request #1950 from travisturner/more-debugf
Add more Debugf() statements to the holder open process
2019-04-30 15:49:21 -05:00
Travis Turner
875c95b2c3
add more Debugf() statements to the holder open process 2019-04-30 15:16:10 -05:00
alanbernstein
962d8c200c
Merge pull request #1961 from alanbernstein/doc-fixes
Fix typos
2019-04-30 12:18:28 -05:00
Alan Bernstein
82f5f632ad Fix typos 2019-04-30 11:48:57 -05:00
Matthew Jaffee
6e24c45631
Merge pull request #1959 from jaffee/1958-apply-schema-all
send POSTed schema to all nodes in cluster
2019-04-30 08:29:07 -07:00
Matt Jaffee
9e6662fb00
send POSTed schema to all nodes in cluster
also fix a *bunch* of tests that weren't closing the clusters they
created. Cleaned up one test to use t.Run instead of just checking
everything in a loop
2019-04-29 19:31:23 -05:00
Matthew Jaffee
e5e7ac3ab5
Merge pull request #1956 from jaffee/1955-post-schema
add ability to post schema using holder.applySchema
2019-04-26 19:09:04 -05:00
Matt Jaffee
a6ee142403
update docs, add test 2019-04-26 18:27:10 -05:00
Cody Soyland
53fb82ea72
remove errant debugging println
Co-Authored-By: jaffee <matthew.jaffee@gmail.com>
2019-04-26 15:55:10 -05:00
Matt Jaffee
0ef3e5e144
add ability to post schema using holder.applySchema
New API warning: this adds ApplySchema to pilosa.API and allows
POSTing to the /schema endpoint
2019-04-25 16:03:44 -05:00
Matthew Jaffee
5bcb00e11a
Merge pull request #1951 from jaffee/revert-validate-shard
remove shard validation stuff
2019-04-23 13:12:34 -05:00
Matt Jaffee
3a07abdeae
remove shard validation stuff
it seems to have a bug where there is some race on cluster startup
which can cause it to think that the node doesn't own any shards.
2019-04-22 17:36:40 -05:00
Travis Turner
07dcb8694a
Merge pull request #1947 from travisturner/lint-fixes
fix some lint warnings raised in VS-Code
2019-04-19 13:36:50 -05:00
Travis Turner
b46ff7b990
fix some lint warnings raised in VS-Code 2019-04-17 18:10:05 -05:00
Matthew Jaffee
4cc1505b2f
Merge pull request #1945 from jaffee/release-v1.3.0
Release v1.3.0
2019-04-16 15:19:35 -05:00
Matt Jaffee
e0a9fd72b7
Release v1.3.0 2019-04-16 14:38:33 -05:00
seebs
564967f7cf
Merge pull request #1924 from seebs/golangci-lint
Golangci lint
2019-04-16 13:44:09 -05:00
Seebs
449c853850 address meta-lint or half-baked lint fixes
Clean up some spelling and consistency issues for the lint
fixes.
2019-04-16 12:08:40 -05:00
Seebs
fc5fc4151b add missing error check 2019-04-16 12:08:40 -05:00
Seebs
302830ed60 fix lint in btree_test 2019-04-16 12:08:40 -05:00
Seebs
ae17fcef7e refix a lint
Another test change made an `err :=` fail because it's no longer
declaring a new variable, but another one needed the :. Or a patch
applied incorrectly. It is a mystery.
2019-04-16 12:08:40 -05:00
Seebs
578ac76011 don't call the golangci-lint workflow anymore
If we're renaming golangci-lint to linter (since it's now
our default linter), we no longer have a workflow named
golangci-lint, so we shouldn't be calling it or requiring
it from other workflows.
2019-04-16 12:08:40 -05:00
Seebs
babcf8c331 continue having a linter target 2019-04-16 12:08:13 -05:00
Seebs
e61e62a695 don't run gometalinter on CI anymore
gometalinter is slow, golangci-lint is fast and checks a lot
more things, let's just use that. We leave the old targets in
the Makefile for now so we can use them for sanity-checking
the results.
2019-04-16 12:07:47 -05:00
Seebs
f15347064f fix race in cluster state transition
The anonymous goroutine, if it gets an error, can race with other
changes. Make the values we intend to call it on parameters so it will
work with those even if other things are happening.
2019-04-16 12:07:18 -05:00
Seebs
9fc8a5b352 handle a specific error that might be an expected error
I'm honestly not sure here.
2019-04-16 12:07:18 -05:00
Seebs
c9cebe21bf unbreak holder node ID logic
The attempt to fix up the logic broke returns from loadNodeID()
in some cases, because it was overwriting the node ID generated
in the IsNotExist case.
2019-04-16 12:07:18 -05:00
Seebs
79451bd53c undo accidental change to test case contents 2019-04-16 12:07:18 -05:00
Seebs
2c6eb66895 check for slightly fewer errors
json.Decoder.Decode() can yield io.EOF which is not actually an
error. This appears to have caused a number of indirect test failures
by making ImportRoaring generally report failure.
2019-04-16 12:07:18 -05:00
Seebs
d5907b2a2e lint fixes to cluster behavior in utils test
This is more lint fixes, but it's less obvious to me what the
right handling for errors is, or whether disregarding them is
safe, so it's a separate commit.
2019-04-16 12:07:18 -05:00
Seebs
77d49ded64 so much lint
So with the switch to a new linter, we get a lot of new warnings,
and the majority of them are harmless probably, but a few might be
real. Variously just use _ to suppress warnings, or report errors.
There's probably things here that deserve better fixes, but we can
always revisit it.
2019-04-16 12:07:18 -05:00
Seebs
20a8c48552 boltdb/attrstore.go: fix up lint about error checking
There's two kinds of unchecked errors here. Writes to a hash
(we don't care, hash functions usually don't error in ways we
care about), and rollbacks of non-writing transactions to a
database. After studying the boltdb docs, I concluded that
the recommended solution is to use the `.View(...)` function
instead of directly controlling the transaction, so I switched
the functions to do that.
2019-04-16 12:06:28 -05:00
Seebs
3070c2d4ac try suppressing modules for golangci-lint 2019-04-16 12:06:28 -05:00
Seebs
d491724461 don't go get -u for golangci-lint
golangci-lint is actually dependent on a specific not-quite
most recent version of golang.org/x/tools, fixing the dependency
is hard and requires changing one of the upstream packages,
just omitting the `-u` lets golangci-lint grab the version it
wants and use that.
2019-04-16 12:06:28 -05:00
Cody Soyland
d84fcb09e7 Workaround due to write permission to bin directory
Pro tip: If you're gonna curl|bash, at least don't curl|sudo bash.
2019-04-16 12:06:28 -05:00
Cody Soyland
258646a7d5 Add golangci-lint to Makefile and CI config 2019-04-16 12:06:28 -05:00
Matthew Jaffee
099dc2d4f3
Merge pull request #1944 from jaffee/update-memberlist
update to latest memberlist fork with race fixes
2019-04-16 10:32:14 -05:00
Matt Jaffee
53aac3b17a
update to latest memberlist fork with race fixes 2019-04-16 09:56:40 -05:00
Matthew Jaffee
ffec2696c8
Merge pull request #1943 from jaffee/error-context
return orig error instead of cause in handler
2019-04-15 11:44:24 -05:00
Matt Jaffee
2414c71812
goimports 2019-04-15 11:15:11 -05:00
Matt Jaffee
27ff1b69c6
fix error messages in test. Fatalf=>Errorf to see more errors. 2019-04-15 08:41:13 -05:00
Matt Jaffee
f8a8a5d096
return orig error instead of cause in handler
also include the invalid name when erroring that a name is invalid.
2019-04-12 21:28:30 -05:00
Cody Soyland
000c188682
Merge pull request #1941 from codysoyland/pr-template-changelog
Add changelog steps to PR template
2019-04-12 14:11:31 -05:00
Cody Soyland
357f0bbf8c Add changelog steps to PR template 2019-04-12 13:47:40 -05:00
Cody Soyland
140c26ceec
Merge pull request #1940 from codysoyland/license-headers
Add license headers and CI check
2019-04-12 13:24:55 -05:00
Cody Soyland
b8ab44eb62 Fix enterprise license header and add shardwidth files to license header check 2019-04-12 11:57:28 -05:00
Cody Soyland
3c1d3e3145 Use bash for check-license-headers target 2019-04-12 11:35:42 -05:00
Cody Soyland
fdbfc68f7c Add license headers to files missing them and CI check to verify they are present. Fixes #1633 2019-04-12 11:30:41 -05:00
Matthew Jaffee
713dbb60ad
Merge pull request #1921 from jaffee/shardwidth22
add support to modify shard width at build time
2019-04-11 11:20:31 -05:00
Cody Soyland
7ede65bf80
Merge branch 'master' into shardwidth22 2019-04-11 10:10:47 -05:00
Travis Turner
980517962f
Merge pull request #1938 from travisturner/duplicate-pql-args
validate (and panic) on duplicate PQL arguments
2019-04-11 09:02:19 -05:00
Travis Turner
02b1f4ae0b
Merge branch 'master' into duplicate-pql-args 2019-04-11 08:39:56 -05:00
Yuce Tekol
61c28d1de4
Merge pull request #1934 from yuce/doc-update
Updated import and client libraries docs
2019-04-11 10:22:27 +03:00
Travis Turner
bdc4f3b07e
recover the duplicate arg panic from parser, treat as error 2019-04-10 23:48:17 -05:00
Yuce Tekol
4df4375db0
Merge branch 'master' into doc-update 2019-04-11 06:16:06 +03:00
Travis Turner
5f079163cb
validate (and panic) on duplicate PQL arguments 2019-04-10 16:34:30 -05:00
Cody Soyland
c4e5b1f434
Merge pull request #1936 from codysoyland/query-response-content-type
Add correct content type to query responses. Fixes #1873
2019-04-10 16:16:19 -05:00
Cody Soyland
7bb6fdffcb Add correct content type to query responses. Fixes #1873 2019-04-10 15:49:33 -05:00
Cody Soyland
8041a9fa5f
Merge pull request #1937 from codysoyland/empty-query-response
Return empty result set when query empty. Fixes #1840
2019-04-10 15:48:16 -05:00
Cody Soyland
992a075cfb Return empty result set when query empty. Fixes #1840 2019-04-10 15:27:12 -05:00
Yuce Tekol
b973f8c963
Merge pull request #1935 from yuce/doc-example-update
Updated examples section
2019-04-10 19:27:49 +03:00
Yuce Tekol
1e7208d60f
the 2019-04-10 17:25:21 +03:00
Yuce Tekol
2fd6287222
recommend 2019-04-10 17:20:02 +03:00
Yuce Tekol
73cc49770c
suggest client libraries for import 2019-04-10 17:17:55 +03:00
Yuce Tekol
cc4de71473
updated examples section 2019-04-10 17:14:47 +03:00
Yuce Tekol
b95f739b07
Updated import and client libraries docs 2019-04-10 15:07:07 +03:00
Matthew Jaffee
55a6fe1eef
Merge pull request #1932 from jaffee/memberlist-fork
replace memberlist dep with patched fork
2019-04-08 12:24:01 -05:00
Matt Jaffee
09e4e20915
replace memberlist dep with patched fork
fixes (hopefully) race condidtion which plagues our CI builds
2019-04-08 08:53:03 -05:00
Matthew Jaffee
2c4f4d7d63
Merge pull request #1931 from jaffee/1919-cluster-race
address race condition by getting cluster nodes with lock
2019-04-06 11:11:49 -05:00
Matt Jaffee
7b436a4e30
remove now-unused cluster.status method 2019-04-06 09:46:39 -05:00
Matt Jaffee
79968e5d2f
fix unlocked access to cluster.nodes 2019-04-05 15:40:25 -05:00
Matt Jaffee
d5cfe880f7
address race condition by getting cluster nodes with lock
needed an unlocked version of sendsync for use within the cluster, so also
implemented that. Added a number of tests trying to reproduce the issue, but was
not able to. Not sure it's worth keeping the new tests.
2019-04-05 15:40:24 -05:00
Matthew Jaffee
b263d8ccdf
Merge pull request #1928 from jaffee/op-apply-simplify
simply setting list of values with *N methods
2019-04-05 16:39:55 -04:00
Matt Jaffee
bd085e0a21
simply setting list of values with *N methods 2019-04-05 14:08:11 -05:00
Matthew Jaffee
9f8d6f6b76
Merge pull request #1930 from jaffee/1843-range-bug
add parser rule to catch old-style Range query
2019-04-05 09:33:32 -04:00
Matt Jaffee
55d9d49f2f
add executor test for deprecated range query style 2019-04-05 07:52:25 -05:00
Matt Jaffee
5458a42ad0
add parser rule to catch old-style Range query 2019-04-04 19:46:02 -05:00
Matt Jaffee
811f1b4124
move build-tagged shardwidth files to subpackage 2019-04-04 14:27:52 -05:00
Matt Jaffee
836b467d3d
add support to modify shard width at build time
use "make <x> SHARD_WIDTH=nn"

fix tests to run and pass at different shardwidths

add shardwidth22 test to circle ci
2019-04-04 13:46:26 -05:00
Cody Soyland
927e8b8942
Merge pull request #1923 from codysoyland/missing-deps
Add missing deps to go.mod/sum
2019-04-01 15:01:08 -05:00
seebs
6bfd0e208e
Merge branch 'master' into missing-deps 2019-04-01 14:47:39 -05:00
Matthew Jaffee
e59e067353
Merge pull request #1925 from jaffee/1922-data-loss
fix data loss bug and robustify test
2019-04-01 14:38:20 -05:00
Matt Jaffee
6130764ede
fix data loss bug and robustify test
Data loss was occuring after a cluster restart. The issue was during the
unmarshaling of the op log when multiple values had been written to the log. The
lines in question were like "changed = changed || b.DirectAdd(v)" in which the
DirectAdd would only be executed when changed was initially false, once it was
true, it would never be executed again.
2019-04-01 14:14:26 -05:00
Cody Soyland
8fcfba7a65 Add missing deps to go.mod/sum 2019-04-01 11:48:24 -05:00
Matthew Jaffee
4f2b757300
Merge pull request #1920 from jaffee/raise-file-map-defaults
increase default max map and file counts [no changelog]
2019-03-29 18:06:48 -05:00
Matt Jaffee
4ed2bfb3ca
increase default max map and file counts
Explained in a comment:

 We default these Max File/Map counts very high. This is basically a
 backwards compatibility thing where we don't want to cause different
 behavior for those who had previously set their system limits high,
 and weren't experiencing any bad behavior. Ideally you want these set
 a bit below your system limits.
2019-03-29 15:39:01 -05:00
Matthew Jaffee
2d28f965ea
Merge pull request #1918 from jaffee/import-value-overwrite-bug
importValue should only consider the last instance of a column id
2019-03-29 14:22:58 -05:00
Matt Jaffee
207b39717b
test both importValue write paths and fix bug
fix large write path—there was a bug because we were iterating backwards over
the small write path to fix that bug, but the large write path needs to iterate
forward. There is enough code difference between the two paths that they are now
two separate methods (which are probably easier to read).
2019-03-29 14:11:06 -05:00
Matt Jaffee
cde954e12f
importValue only considers the last instance of a column id
included test demonstrates bug
2019-03-29 13:37:22 -05:00
seebs
80930de295
Merge pull request #1916 from seebs/seebs/btree
improve btree performance a bit, add some testing for it.
2019-03-29 12:08:51 -05:00
Seebs
3b2745e47a inline cmp
Since we always use the same cmp function, we don't need to
actually *call* a function -- we can just inline it. Or, in
fact, omit the computation entirely; comparing the result of
the subtraction to zero is (very slightly) more expensive than
comparing the magnitudes of two numbers.

Also fix a spurious comment and gofmt issues.
2019-03-28 15:42:27 -05:00
Seebs
8fb8bb3609 add btree tests
The upstream btree code has a test file, this is an import
of that test file, adjusted/adapted to make it work with our
de-genericized uint64/*Container implementation, so we have some
tests and benchmarks available for the btree implementation itself.
2019-03-28 15:42:00 -05:00
Seebs
aab42e97a4 tune b+tree values
Did some benchmarking with b+tree values. The actual interactions
appear to be slightly inconsistent; some values seem to help more
in cases with higher OpN in benchmarks, others with lower OpN. It
appears that the practical consideration may be what happens
when a snapshot gets triggered; smaller kx/kd appear to reduce
costs there, but increase costs between snapshots. This is a
bit of guesswork.

Numbers are slighly under powers of 2, because that means that the
total actual sizes of k and d end up fitting nicely in alloc
pool sizes.
2019-03-28 15:42:00 -05:00
Matthew Jaffee
71e7f62909
Merge pull request #1917 from jaffee/perf-regression
fix importRoaring perf regression [no changelog]
2019-03-28 15:35:08 -05:00
Matt Jaffee
1aafd95adc
make arg naming consistent 2019-03-28 15:11:08 -05:00
Matt Jaffee
c651ff9299
use BTree bitmap in importRoaring
sliceContainers very slow to union into
2019-03-28 13:49:01 -05:00
Matt Jaffee
77a0b6b353
add pathological import benchmark 2019-03-28 13:49:00 -05:00
Matthew Jaffee
5ee49904b5
Merge pull request #1915 from jaffee/benchmarking-tweaks
run fewer concurrency level benchmarks, add bench Makefile target
2019-03-28 12:03:29 -05:00
Matt Jaffee
e9db8eb2c2
run fewer concurrency level benchmarks, add bench Makefile target
The benchmarks take an absurdly long time to run, and I think these are the
largest offenders. Dropping to two concurrency cases 2 and 16 should give a
pretty good idea.
2019-03-27 13:32:56 -05:00
seebs
4955dff22f
Merge pull request #1859 from seebs/seebs/serverinfo
add server stats to /info endpoint
2019-03-26 11:10:37 -05:00
Seebs
5ee87bbf7c add server stats to /info endpoint
report the approximate hardware specs (CPU speed, cores, memory)
of the server in the /info endpoint. This may be useful when
benchmarking.

We do some workarounds because gopsutil's core count output is
confusingly different between Linux and Darwin, and the MHz output
is usually wrong on Linux. Intel's app notes say to just parse
the model string. Whyyyyyyy.
2019-03-26 09:14:51 -05:00
Matthew Jaffee
5e0413eac1
Merge pull request #1911 from jaffee/importValue-data-race
test concurrent value imports, fix race
2019-03-25 16:23:17 -05:00
Matt Jaffee
714f89c65c
simplify locking in importValue
may be a slight perf cost, but the simplicity is well worth it
2019-03-25 14:27:05 -05:00
Matt Jaffee
4420d72196
test concurrent value imports, fix race 2019-03-25 14:25:22 -05:00
Matthew Jaffee
9fda9cf6a3
Merge pull request #1910 from jaffee/profiling-stuff
implement config options for block profile rate and mutex fraction
2019-03-25 14:24:36 -05:00
Cody Soyland
52062c0a27
linkify SetMutexProfileFraction in docs
Co-Authored-By: jaffee <matthew.jaffee@gmail.com>
2019-03-25 13:45:43 -05:00
Cody Soyland
54a6e0ef84
linkify SetBlockProfileRate in docs
Co-Authored-By: jaffee <matthew.jaffee@gmail.com>
2019-03-25 13:45:28 -05:00
Matt Jaffee
9f4a9421bc
fix missing quote in toml tag. unclear how test could pass without it 2019-03-25 12:16:24 -05:00
Matt Jaffee
599b2f4a9e
implement config options for block profile rate and mutex fraction
set sane defaults. The performance overhead seems to be negligible, and this will allow us to obtain mutex and blocking profiles from running Pilosas by default.
2019-03-25 11:38:01 -05:00
Matthew Jaffee
b031b45cbe
Merge pull request #1906 from jaffee/1905-close-files
implement global open file counter using syswrap
2019-03-25 09:53:38 -05:00
Matt Jaffee
53dfa9b7f2
remove rename of columnIDs and add comment 2019-03-23 14:52:16 -05:00
Matt Jaffee
e7f65cf7be
implement global open file counter using syswrap
close files after using them if global max is passed.

I originally implemented this without the global count—just always closing files
when done with them, and reopening for new writes. This was crazy slow for that
one test that uses mustSetBits in a big loop. I modified the test to use
importRoaring and everything worked better (though much more slowly).

After adding the global counter, I ran the tests with that one test using
mustSetBits again, and the performance was similar to master. After completing
this PR, I ran the tests with the max limit set to 5—they still passed but were
much slower.
2019-03-23 14:52:16 -05:00
Cody Soyland
b24bc8bb4b
Merge pull request #1909 from codysoyland/golang-1.12
Add Go 1.12 to CircleCI
2019-03-22 20:30:15 -05:00
Cody Soyland
3096202980 Make workflow require Go 1.12, not Go 1.11 2019-03-22 17:20:08 -05:00
Cody Soyland
38af019113 Default to Go 1.12 2019-03-22 17:06:17 -05:00
Cody Soyland
20137986e5 Add Go 1.12 to CircleCI 2019-03-22 16:59:20 -05:00
seebs
0678c539a1
Merge pull request #1901 from seebs/seebs/smallc
make Containers smaller, especially when they have small contents
2019-03-22 16:56:44 -05:00
Seebs
35593f99df move comment to right place 2019-03-22 16:31:29 -05:00
Seebs
bdbd9c1f47 add missing BCE slices in intersection 2019-03-22 16:31:29 -05:00
Seebs
cd81a9a33f hint to the bounds checker for bitmapRepair
You might wonder why `i <= bitmapN-4`. Answer: The compiler isn't
smart enough for the stride analysis to figure out that `i <= bitmapN`
actually guarantees that. If you set the limit to something not a
multiple of stride, though, it can't figure out *anything* about
things. But for some reason, `i < bitmapN-3` fails badly (it
actually adds bounds checks not present with `i < bitmapN`), but
`i <= bitmapN - 4` works.

This reduces runtime of bitmapRepair by about 14%.
2019-03-22 16:31:29 -05:00
Seebs
8475b97d87 set cap more carefully on unsafe slices
Treating a pointer as a pointer to a large array of bytes,
or converting back the other way, isn't totally insane, but
it does create slices with an extremely large cap. This bit
me while I was trying to build the 16-byte packed Container
structure, but it's probably actually worth fixing in general.
2019-03-22 16:31:29 -05:00
Seebs
8041785ea4 clean up some leftover bits from previous implementation
It used to be useful/desireable to set the other slices to nil when
setting a new slice type, it's no longer useful, take some of those
out.

Also reuse the already-computed run count when converting arrays
and bitmaps to runs.
2019-03-22 16:31:29 -05:00
Seebs
2af5d64e2c unbreak a subtle breakage that only test cases could hit
It turns out the logic for "don't update everything if
the incoming slice pointer is the stash" is wrong; it should
really be "don't update everything if the incoming slice
pointer is the one we already have".

The reason this breaks is that one of the tests directly
sets the mapped bit. This breaks my assumption that we'd
never be using the stash and have the mapped bit set, and
that in turn breaks my assumption that the pointer
of an incoming array can't be the stash address unless
we were previously using the stash. If unmap moved us
to non-stashed memory, then a future write could try to
write, notice that it would fit in the stash, copy the
data ... and not update the pointer because the stash
pointer was handled separately.

This way, if you do that, you can end up not using the
stash when you probably could, but you get the expected
behavior. But also, don't set the mapped bit directly.
(I guess there's a good reason to for the test case,
which is using it to verify that unmaps happen when
modifications happen.)

Also the unmap functions should indicate that they have
successfully unmapped, which may help performance in
some test cases.
2019-03-22 16:31:29 -05:00
Seebs
5c8106bead drop slice implementation
The actually-a-slice implementation of Container was useful in
debugging but does not spark joy.
2019-03-22 16:31:29 -05:00
Seebs
45e8978835 messing around with the performance of unmap
Noticed in profiling that unmap wasn't being inlined. Also noticed
that every call is on a specific container type, so now they're
specialized and small enough to inline.
2019-03-22 16:31:29 -05:00
Seebs
117942c0f3 Add stash-based implementation of Container
This implementation, controlled by the build flag "container24s",
is similar to the single-slice container implementation, but goes
a bit further. First, instead of using a native slice as its internal
storage, it uses pointer/len/cap as distinct values, and only int32
ranges for len and cap. Second, it has a small region of additional
storage which it uses as a backing store by default for arrays or
runs. The idea is that, if you request a new empty array container,
you get one with a pre-allocated virtual slice big enough for five
values, actually stored in the Container. This is useful because
Go's allocator has size classes for 16 and 32 bytes, and the
Container comes in at 24 bytes worth of storage -- meaning that if
you allocate a container, you're allocating 32 bytes anyway, so we
might as well use that space to avoid extra allocations.

This includes some test fixups because DeepEqual was testing
too much equality in some tests.

Also, we simplify unionArrayArray to postpone creating a Container
until we're ready.
2019-03-22 16:31:29 -05:00
Seebs
47dcb5b4a7 Abstract away access to container slices
On a 64-bit machine, the slices in a Container consume 72
bytes, and the Container itself is 80. But we only use one
slice at a time! This patch shifts us to keeping a single
slice in the Container, and converting provided slices to
and from that type when we want to update it. (It is not
safe to access the slice through the wrong type.)

We also add some new tests, conditional on a build tag
called `roaringparanoia`. These tests will be optimized
away entirely by the compiler when the tag isn't
present, because the conditionals use a const. These catch
possible errors like trying to access the bitmap slice
of a non-bitmap container.

We also eliminate all direct creation of Container literals,
so we can mess with the internals more. (On reflection
and study, we decided not to go to the fancier design where
references to .n and .typ were also converted to function
calls, which would have allowed packing those attributes
more tightly, because it was a lot more overhead and a lot
of work to keep track of.)

There's some circumstances where we appear to have been
relying on incorrect guesses about the nature of containers.
For instance, in xorBitmapRun, there's logic that makes sense
only if the output's a run container, but it's not, it's a
bitmap container. This creates strange behavior sometimes,
though. Several of these are corrected now.
2019-03-22 16:31:29 -05:00
Matthew Jaffee
86ea040639
Merge pull request #1908 from jaffee/bitmap-any-quick-fix
quick fix for Bitmap.Any bug [no changelog]
2019-03-21 16:09:59 -05:00
Matt Jaffee
d202e6a1a0
quick fix for Bitmap.Any bug
Want to make empty containers a thing of the past, but that can wait for another
day.
2019-03-21 15:46:19 -05:00
Matthew Jaffee
7550b5445a
Merge pull request #1900 from jaffee/validate-shard
Validate shard
2019-03-20 23:06:22 -05:00
Matt Jaffee
33b54c68d5
add lock on cluster.OwnsShard 2019-03-20 22:04:20 -05:00
Matt Jaffee
97ba8771bc
add test for only opening owned shards 2019-03-20 22:04:20 -05:00
Todd Gruben
418a8788ed
gofmt missing 2019-03-20 22:04:20 -05:00
Todd Gruben
186f034b16
missed commit 2019-03-20 22:04:20 -05:00
Todd Gruben
8edd2b3d13
applied travis suggestions 2019-03-20 22:04:20 -05:00
Todd Gruben
27492a11cc
some formating issues 2019-03-20 22:04:19 -05:00
Todd Gruben
38de65eac0
only load shards that are applicable to node 2019-03-20 22:04:19 -05:00
Matthew Jaffee
66d750bd53
Merge pull request #1904 from jaffee/mmap-fail-docs
add config docs for max-map-count
2019-03-19 20:04:51 -05:00
Matt Jaffee
a7e77566a4
add config docs for max-map-count 2019-03-19 16:21:24 -05:00
Matthew Jaffee
f299473658
Merge pull request #1903 from jaffee/mmap-fail
Mmap fail
2019-03-19 14:02:14 -05:00
Matt Jaffee
226f15446b
lock MaxMapCount and fix unused var 2019-03-19 12:55:26 -05:00
Matt Jaffee
e469285fe3
add fragment mmap tracking and limiting
in the case that the map limit is reached, we'll fall back to reading the file
into memory normally.
2019-03-19 12:55:26 -05:00
Todd Gruben
327aa70924
add failure path for mmap 2019-03-19 12:55:25 -05:00
seebs
b2eff07d8d
Merge pull request #1897 from seebs/seebs/inplace
Address UnionInPlace performance regressions
2019-03-15 12:02:10 -05:00
Seebs
cf5f9f9a57 add clarifying comment 2019-03-15 11:19:49 -05:00
Seebs
97486f410b WIP: Union/UnionInPlace performance improvements
This consolidates a number of changes. The first is significant
reductions in allocation and copying during UnionInPlace
operations on very sparse containers -- for instance, combining
two array containers with one item each.

We fix up the logic for identifying and handling cases where
only one of the containers being unioned together has a given
key.

We generally favor cloning an existing container over unioning
it into a new empty container.

When unioning two containers, we were using unionIntoTargetSingle
on those two containers, into an empty bitmap. For more, we were
creating an empty bitmap, then unioning all the others into
it; it's faster to clone the first, then union the others into
it.

The overall logic for UnionInPlace is cleaned up and simplified
a bit. However, it's then complexified a bit, because it turns
out that while it's a bad idea to convert single-item arrays to
bitmaps to union them, by a few hundred items, the bitmap
conversion saves a lot of time even if it costs an allocation.

The value of N picked here is sort of arbitrary, but
512 seems to be about right. The big problem is a massive
performance hit in cases where, say, there's only a
couple of items per container, and the bitmap conversion
is extremely expensive. If you wait until N reaches
the array size cap, though, you take a very noticeable
performance hit (can be a factor of 2.5-3 in simple
testing).

We also add some stat counters, and rename an internal
method on the `handledIters` type.
2019-03-14 15:17:38 -05:00
Seebs
054cb206d5 improve union-related benchmarking
Add a benchmark to test a specific case where UnionInPlace is
underperforming the naive union operation badly.

Also, the UnionBulk test was reusing a bitmap, meaning that it ended
up doing a lot of unions into a bitmap that already had all the
bits it was supposed to have. This broke a couple of other tests
in unexpected ways.

We also now use UnionInPlace in importRoaring, and test it
in the container combinations tests via a wrapper.
2019-03-14 15:16:49 -05:00
Matthew Jaffee
53d018a2b1
Merge pull request #1892 from jaffee/import-roaring-union
smallWrite path for import-roaring
2019-03-12 08:16:25 -05:00
Matt Jaffee
a28141c466
revert to Union for importRoaring
UnionInPlace is still heavily affected by
https://github.com/pilosa/pilosa/issues/1875 where containers that exist in an
incoming bitmap can cause massive unnecessary allocations of bitmap containers
when an array of short length is all that's needed.
2019-03-11 17:43:55 -05:00
Matt Jaffee
52d43fb4e2
add smallPath for importRoaring
this converts the rowSet to a map from a slice which might be bad... benchmarks
will tell.
2019-03-11 17:43:55 -05:00
Matt Jaffee
d0f8304f1c
add importRoaring small updates benchmark 2019-03-11 17:43:55 -05:00
Matt Jaffee
19807ff3a7
use num containers to decide which direction to union
avoids doing a potentially expensive f.storage.Count()
2019-03-11 17:43:55 -05:00
Matt Jaffee
e33ca2d0ae
use UnionInPlace in import-roaring
get the count of the existing fragment and compare it to the incoming bits to
decide which should be unioned into the other. This should generally result in
far fewer allocations, though there is much work that needs to be done within
UnionInPlace to further improve things.

unrelatedly, I added a TODO to change the long-query-time option to move it out
of cluster. It should probably be happening at the API level so that different
handlers can reuse it, but if we're going to do that we'll want to make sure
that any potentially time intensive operations are pulled into api from
handler (e.g. protobuf decoding)
2019-03-11 17:43:55 -05:00
Matt Jaffee
663c725779
import benchmarking tweaks
importRoaring large fragment benchmark

skip concurrent import benchmarks with testing.short
2019-03-11 17:43:07 -05:00
Matthew Jaffee
6f9bac960e
Merge pull request #1871 from jaffee/1864-random-import-perf
1864 random import perf
2019-03-07 10:55:22 -06:00
Matt Jaffee
9fe58e5e36
exterminate unnecessary sprintf 2019-03-07 10:24:41 -06:00
Matt Jaffee
b71096b688
update licensing and NOTICE to reflect btree being moved to roaring 2019-03-05 15:52:32 -06:00
Matt Jaffee
831195e7d2
update roaring container benchmarks to do both slice and btree 2019-03-05 15:46:13 -06:00
Matt Jaffee
e54dbd6731
simplify row/lastRow comparison in bulkImport 2019-03-05 12:20:21 -06:00
Matt Jaffee
cfb2a80866
write large fragment import benchmark
needed to pull in btree containers to get acceptable perf building the initial
data. Still quite slow though.
2019-03-05 08:48:33 -06:00
Matt Jaffee
6fe1ab45c2
fixup Fragment_Import benchmark
It was doing a fresh import on the first round and then importing the same data
into the fragment over and over.
2019-03-05 08:47:44 -06:00
Matt Jaffee
7af64e382c
comments to make import mutex less confusing 2019-03-04 21:38:09 -06:00
Matt Jaffee
8476fffaa7
always operate on storage in importPositions regardless of smallWrite
This greatly simplifies the code, and with the recent addition of DirectAddN and
DirectRemoveN should be as or more performant than doing the separate bitmap and
union (in most cases, unsorted data could still be slower). Perhaps more
importantly, it is also less allocation heavy than the union approach. Also
makes it trivial to get the counts of changed bits, so I've cleaned up the stats
to show number of bits we're importing/clearing and the number of bits that
actually changed.
2019-03-04 21:38:09 -06:00
Matt Jaffee
868342d338
fix benchmarks broken by import modifying its args in-place 2019-03-04 21:38:08 -06:00
Matt Jaffee
4c42069d5d
implements bitmap batch Direct* operations which are optimized for sorted data
also reset the data on AddN and RemoveN ops if the log write fails
2019-03-04 21:38:08 -06:00
Matt Jaffee
c32c8cda84
only write changed values to op log 2019-03-04 21:38:08 -06:00
Matt Jaffee
9b8a97ccb6
maintain column set in bulkImportMutex to guard against repeats 2019-03-04 21:38:08 -06:00
Matt Jaffee
4082ce655a
wip on adding mutex support to random import perf 2019-03-04 21:38:08 -06:00
Matt Jaffee
f06a9f0e6e
positionsForValue appends to existing slices rather than allocating small ones 2019-03-04 21:38:08 -06:00
Matt Jaffee
a58459cf0f
fix spelling of unnecessary 2019-03-04 21:38:08 -06:00
Matt Jaffee
d429d7c496
code review feedback: add Bitmap.Any and remove unecessary condition 2019-03-04 21:38:07 -06:00
Matt Jaffee
023faebd90
fix bug where opN wasn't getting set/cleared correctly 2019-03-04 21:38:07 -06:00
Matt Jaffee
7037ebf4b3
rename smallPath->smallWrite for consistency 2019-03-04 21:38:07 -06:00
Matt Jaffee
088d618040
increase default MaxOpN 2019-03-04 21:38:07 -06:00
Matt Jaffee
04957308ba
gofmt -s 2019-03-04 21:38:07 -06:00
Matt Jaffee
3cbcb238fb
aggregate small bsi imports into a single-write append 2019-03-04 21:38:07 -06:00
Matt Jaffee
ce656bbcda
factor out code to import/clear by positions 2019-03-04 21:38:07 -06:00
Matt Jaffee
537ae99fb9
add import support with aggregated op log writes 2019-03-04 21:38:07 -06:00
Matt Jaffee
dd4a8755ae
add importValue benchmark and move data building to per benchmark 2019-03-04 21:38:06 -06:00
Matt Jaffee
0de419c95e
add a SetBit/ClearBit path to bulkImport for small updates
also add benchmarks for this situation and set default MaxOpN higher which
benchmarks suggest is a good idea
2019-03-04 21:38:06 -06:00
Matthew Jaffee
5027a7a883
Merge pull request #1887 from jaffee/metric.service-fix
[fix] improve help strings for metrics options
2019-03-04 21:37:34 -06:00
Matt Jaffee
52fe460f84
improve help for metrics options 2019-03-04 17:36:01 -06:00
Yuce Tekol
3f5feeb83c
Merge pull request #1881 from yuce/1880-shardwidth-in-indexinfo
Adds shardWidth to index info in schema
2019-03-01 18:08:24 +03:00
Yuce Tekol
d8ba398dd8
added missing index.go changes 2019-03-01 15:02:49 +03:00
Yuce Tekol
767062ab7c
Adds shardWidth to index info in schema 2019-03-01 14:57:46 +03:00
Matthew Jaffee
784cadd1b1
Merge pull request #1876 from jaffee/union-in-place-unmap
[fix] make sure to unmap containers before modifying
2019-02-26 11:13:56 -06:00
Matt Jaffee
67e7281a55
make sure to unmap containers before modifying 2019-02-25 17:12:27 -06:00
seebs
5b43c90762
Merge pull request #1863 from seebs/seebs/flock
avoid probable race when creating fragments
2019-02-21 20:17:23 -06:00
Seebs
dde6954de4 view.go: deal with races in fragment creation
There existed a case where two goroutines would try to
CreateIfNotExists the same fragment, and the first would
create it, but not put it in the fragments table, then
drop the lock, try to broadcast a message, and if it
succeeded then populate the fragments table. The second
would come along during the broadcast, not find an
entry, try to create one, and fail because the file was
already locked.

Basic problem: At least one test in server/ will fail
if we don't delay to send out broadcast messages. Everything
will lock up if we can wait forever (or even just a very
long time) for the message broadcast. We don't ever want
to have an inconsistent state -- so we don't want to either
fail to get a fragment when one's been created, or get one
that's about to be deleted if the broadcast fails.

So, creation and stashing in the fragments table is
atomic and immediate. After that, we optimistically attempt
to broadcast. If we fail, we fail. We delay up to about
50ms for the broadcast to be done, but after that return
anyway. This way, if things are going well everything
works, and if there's unexpected delays, things work except
some nodes in a cluster may not know about available
shards on other nodes sometimes. But that would have
happened anyway. A proper fix is beyond the scope of this
patch.
2019-02-21 16:43:19 -06:00
tgruben
11fe06be85
Merge pull request #1865 from tgruben/roaring-import-opt
removed copy for pilosa roaring files
2019-02-19 11:21:51 -06:00
Todd Gruben
e3fe55522d comment adjustments 2019-02-19 10:54:09 -06:00
Todd Gruben
02ed4568dd gofmt 2019-02-19 10:25:34 -06:00
Todd Gruben
a13e5fafa4 updated comments and added error wrapping 2019-02-19 10:19:17 -06:00
Todd Gruben
ffe1a285bd removed copy for pilosa roaring files 2019-02-18 16:28:37 -06:00
Cody Soyland
62b9697a6a
Merge pull request #1616 from codysoyland/go-module
Go module support
2019-02-07 12:09:38 -06:00
Cody Soyland
44f6b1d0e3 Regenerate go mod files 2019-02-07 11:46:30 -06:00
Cody Soyland
a9b8b352fc Go mod should be enabled here 2019-02-07 10:49:40 -06:00
Cody Soyland
8ffc4537b7 Ensure Go modules disabled during installation of tools 2019-02-07 10:44:46 -06:00
Cody Soyland
9ebe428824
Merge branch 'master' into go-module 2019-02-06 14:12:17 -06:00
Matthew Jaffee
755c1f4238
Merge pull request #1858 from jaffee/missing-doc-heading
add Group By heading to query language docs
2019-02-06 13:27:36 -06:00
Matt Jaffee
75d91e9b63
add Group By heading to query language docs 2019-02-06 12:49:57 -06:00
Cody Soyland
30143cf44e Fix config passing 2019-02-04 09:32:51 -06:00
Cody Soyland
4bef33eaa9 Address code review feedback 2019-02-04 08:56:32 -06:00
Travis Turner
8be84b7c76
Merge pull request #1851 from travisturner/rows-time-range
add from/to range arguments to Rows() call
2019-02-03 11:00:48 -06:00
Travis Turner
31e0371a55
update the rows range query docs to match the logic 2019-02-02 21:57:03 -06:00
Travis Turner
a0a641c541
remove extra nesting 2019-02-01 16:46:45 -06:00
Travis Turner
87b3438cb1
add logic to restrict time range to available views 2019-02-01 15:30:10 -06:00
Travis Turner
b544328647
parseTime() function to handle interface to time parsing 2019-01-31 18:29:32 -06:00
Travis Turner
a242b8cbaf
add from/to range arguments to Rows() 2019-01-30 16:27:07 -06:00
alanbernstein
839371711c
Merge pull request #1849 from alanbernstein/docs-fixes
Docs fixes
2019-01-30 15:49:09 -06:00
Alan Bernstein
6144988774 Clarify comparison operator usage 2019-01-29 16:58:32 -06:00
Alan Bernstein
5e614432b8 Fix formatting 2019-01-29 16:35:51 -06:00
Alan Bernstein
05703cfff4 Fix links 2019-01-29 16:35:37 -06:00
Cody Soyland
188b977633 Add go module support 2019-01-29 14:53:03 -06:00
Travis Turner
71c2053016
Merge pull request #1848 from travisturner/clearrow-translate
ensure ClearRow() arguments get translated
2019-01-29 13:21:32 -06:00
Travis Turner
30711664e8
ensure ClearRow() arguments get translated 2019-01-29 12:36:54 -06:00
Travis Turner
988d5a6156
Merge pull request #1846 from travisturner/columnattrs-json
prevent omitting zero ids on columnattrs
2019-01-28 14:48:11 -06:00
Travis Turner
687b67dc54
prevent omitting zero ids on columnattrs 2019-01-28 13:16:43 -06:00
Yuce Tekol
62e38dbffa
Merge pull request #1829 from yuce/internal-85-test-windows-support
Updated Docker and Windows sections in the docs
2019-01-28 21:35:03 +03:00
Yuce Tekol
bcb1ccbc2f
Merge branch 'master' into internal-85-test-windows-support 2019-01-28 21:27:13 +03:00
Travis Turner
fc3c5dcb1d
Merge pull request #1842 from travisturner/cache-type-none-size
set cache size to 0 if cache type is none
2019-01-28 09:16:04 -06:00
Travis Turner
198a2910f2
set cache size to 0 if cache type is none 2019-01-25 14:51:00 -06:00
tgruben
f3941f5aa1
Merge pull request #1761 from tgruben/shift-op
Shift operator
2019-01-25 14:21:25 -06:00
Travis Turner
113c6998be
add Shift() to query docs 2019-01-25 14:08:49 -06:00
Travis Turner
779f89815d
Merge branch 'master' into shift-op 2019-01-25 12:57:51 -06:00
Travis Turner
8fe966e8a0
Modifying some of the logic around Shift()
add some comments to the shift() logic
improve test coverage
fix full bitmap overflow
add support to specify shift-by amount
2019-01-25 12:54:44 -06:00
Travis Turner
636513f843
Merge pull request #1832 from travisturner/advertise-addr
support advertise address and listen on 0.0.0.0
2019-01-24 18:12:16 -06:00
Travis Turner
cd7d4ecc22
Merge branch 'master' into advertise-addr 2019-01-24 17:55:51 -06:00
Matthew Jaffee
9880f0a20c
Update docs/configuration.md
Co-Authored-By: travisturner <travis@pilosa.com>
2019-01-24 17:55:25 -06:00
Travis Turner
2467d88ddc
Merge branch 'master' into shift-op 2019-01-24 13:56:28 -06:00
Travis Turner
96d61fe034
Merge pull request #1793 from WaaX/patch-3
Replaced seed with seeds
2019-01-24 09:34:07 -06:00
Travis Turner
fa975411b7
change seeds examples from string to list 2019-01-24 09:20:01 -06:00
WaaX
8062fc6ea7
Replaced seed with seeds
Cluster config referred to seed but the server now expects seeds
2019-01-24 09:17:43 -06:00
tgruben
923e67959c
Merge pull request #1839 from tgruben/numbytes
added convenience function to efficiently calculate size of a roaring bitmap in bytes
2019-01-23 18:04:18 -06:00
Todd Gruben
c2ca00ebe8 force bitmap creation on test; for real this time 2019-01-23 17:05:40 -06:00
Todd Gruben
cb08749967 correct bitmap test 2019-01-23 16:47:59 -06:00
Todd Gruben
4436bce943 Merge branch 'numbytes' of github.com:tgruben/pilosa into numbytes 2019-01-23 13:50:40 -06:00
Todd Gruben
790123410f metalinter fix 2019-01-23 13:50:01 -06:00
tgruben
374caa4746
Merge branch 'master' into numbytes 2019-01-23 13:36:35 -06:00
Todd Gruben
15494becac formatting 2019-01-23 13:35:27 -06:00
Todd Gruben
374fc9deff added convience function to calculate size of bitmap in bytes
completed test converage
2019-01-23 13:30:41 -06:00
Travis Turner
e15f054075
update docs for advertise, gossip.advertise-host, gossip.advertise-port 2019-01-22 14:22:39 -06:00
Travis Turner
efb9f97e61
Advertise address and listen on 0.0.0.0
This commit adds support for advertise address by using a new config
option `advertise`, or by defaulting its value to that
specified in `bind`.

Also adds support for listening on 0.0.0.0 by trying to determine
the preferred outbound IP to use for the advertise address.
2019-01-21 22:36:55 -06:00
Matthew Jaffee
b86f0c677d
Merge pull request #1831 from jaffee/bench-temp-dir
make sure more tests and benchmarks can have their temp dir set by flag
2019-01-21 16:44:54 -06:00
Matt Jaffee
b7973b75f1
get rid of init 2019-01-21 16:23:28 -06:00
Matt Jaffee
04c7ab5034
add nolint for init 2019-01-21 16:23:27 -06:00
Matt Jaffee
fe7b926773
make sure more tests and benchmarks can have their temp dir set by flag
This is to allow the directory to be set to where a particular disk is mounted
during benchmarking.
2019-01-21 16:23:27 -06:00
Matthew Jaffee
1c470e4c10
Merge pull request #1834 from seebs/seebs/deadlock
prevent deadlock in replication logic on reopening a store
2019-01-21 16:21:46 -06:00
Matthew Jaffee
3bbd3cbfb1
Merge branch 'master' into seebs/deadlock 2019-01-21 15:33:41 -06:00
Matthew Jaffee
7b8589bdab
Merge pull request #1835 from jaffee/log-nil-fix
pass loggers around properly in gossip
2019-01-21 15:33:22 -06:00
Matt Jaffee
bb9f3a95d2
move legacy field check to non-concurrent code 2019-01-21 15:17:33 -06:00
Matt Jaffee
44270fe9fd
rename memberlist.logger and add explanatory comments 2019-01-21 14:47:02 -06:00
Matt Jaffee
6f4dee5e31
pass loggers around properly in gossip 2019-01-21 14:47:02 -06:00
Matthew Jaffee
36c38808f4
Merge pull request #1837 from jaffee/staticcheck-fixes
Staticcheck fixes (lint)
2019-01-21 14:46:23 -06:00
Matt Jaffee
20e06b7b0f
fix direct usage of std log instead of configured logger 2019-01-21 14:39:24 -06:00
Matt Jaffee
f1ecead069
fix failing tests due to staticcheck fixes 2019-01-21 14:38:58 -06:00
Matt Jaffee
daa87d8e12
fix staticcheck warnings 2019-01-21 14:24:11 -06:00
Yuce Tekol
d0f7115c91
Merge pull request #1830 from yuce/1805-rows-call-format
Fixes #1805. Fixes Store call error messages
2019-01-21 22:31:43 +03:00
seebs
7961f87430
Merge branch 'master' into seebs/deadlock 2019-01-21 13:31:21 -06:00
Yuce Tekol
b898460a18
Merge branch 'master' into 1805-rows-call-format 2019-01-21 18:35:05 +03:00
Yuce Tekol
1d3fafa207
trivial 2019-01-21 18:32:58 +03:00
Travis Turner
2e6635ec6d
Merge pull request #1836 from travisturner/cluster-nodes-rlock
cluster.Nodes() just needs a read lock
2019-01-21 09:30:50 -06:00
Yuce Tekol
511f7de422
added staticcheck to gometalinter target 2019-01-21 18:29:42 +03:00
Yuce Tekol
7531c337a9
removed megacheck from metalienter target 2019-01-21 18:23:40 +03:00
Yuce Tekol
21c0a5e3de
Merge branch 'master' into 1805-rows-call-format 2019-01-21 18:03:50 +03:00
Yuce Tekol
773d661b68
GroupBy legacy Rows 2019-01-21 18:02:51 +03:00
Travis Turner
fc1de2dba9
cluster.Nodes() just needs a read lock 2019-01-18 14:49:58 -06:00
Seebs
cd534af430 prevent deadlock in replication logic on reopening a store
Depending on where in the replicate() loop you are when a
store is closed or reassigned, it's possible for it to deadlock.
The deadlock would be that replicate has just successfully read an
entry from your PrimaryTranslateStore.Reader, when a new
PrimaryTranslateStore event happens. Then handlePrimaryTranslateStore
grabs the mutex, signals that the replication handler should
close, and waits for the replication handler to close. Meanwhile,
the replicate() loop tries to grab the mutex... and deadlocks.

Solution: Make the replicate() loop part that needs the mutex
a goroutine that signals on a channel, so we can put it in a select
along with checking for the replicationClosing signal (or the
context terminating). If one of those happens, replicate()
terminates, allowing monitorReplication() to return, which
causes the anonymous function which called it to call
repWG.Done(), allowing handlePrimaryTranslateStore to continue
and eventually release the mutex. At some later point, appendEntry
succeeds or fails, dumps its result status in a buffered
channel, and exits, and the buffered channel is garbage collected.

This is way simpler than it sounds, but it took me a while
to figure out how simple it was.
2019-01-18 13:24:24 -06:00
seebs
8762c2a4dc
Merge pull request #1763 from seebs/seebs/bench
improve  sliceascending/slicedescending benchmarks.
2019-01-18 09:17:00 -06:00
Yuce Tekol
ca7dc073ab
Merge branch 'master' into 1805-rows-call-format 2019-01-18 17:48:58 +03:00
Yuce Tekol
5fb82ac7b3
Rows sets _field if field is set 2019-01-18 17:46:20 +03:00
Yuce Tekol
c30f9bc192
Rows accepts a fields param for backward compat. 2019-01-18 17:41:54 +03:00
seebs
a2005d556c
Merge branch 'master' into seebs/bench 2019-01-17 23:43:15 -06:00
Travis Turner
86e9456afc
Merge pull request #1826 from travisturner/error-time-nostandardview
raise an error on Rows() query against a time field with noStandardView: true
2019-01-17 21:36:44 -06:00
Travis Turner
9ce319eeee
Merge branch 'master' into error-time-nostandardview 2019-01-17 14:48:36 -06:00
Matthew Jaffee
6f21eb32de
Apply suggestions from code review
Co-Authored-By: travisturner <travis@pilosa.com>
2019-01-17 14:47:35 -06:00
seebs
7857730b7f
Merge branch 'master' into seebs/bench 2019-01-17 13:48:19 -06:00
Yuce Tekol
0542f79442
made docker its own section 2019-01-16 20:58:52 +03:00
Yuce Tekol
dc735c17b8
Fixes #1805. Fixes Store call error messages 2019-01-16 20:52:33 +03:00
Yuce Tekol
e4e338e7f9
Updated Docker and Windows sections 2019-01-16 15:35:27 +03:00
seebs
63255315b1
Merge pull request #1820 from seebs/seebs/setvaluebenchmarks
setValue test and benchmark updates
2019-01-15 16:00:27 -06:00
seebs
4e592b4b8a
Merge branch 'master' into seebs/setvaluebenchmarks 2019-01-15 15:04:41 -06:00
Travis Turner
173bfb8b3c
Merge pull request #1827 from travisturner/keep-sample-fragment-data
don't delete test fragment data (part of repo)
2019-01-15 11:39:35 -06:00
tgruben
e5df52836e
Merge branch 'master' into shift-op 2019-01-15 08:57:28 -06:00
Travis Turner
0a8bd6548b
don't delete test fragment data (part of repo) 2019-01-14 17:15:30 -06:00
Travis Turner
44f53a5f1d
raise an error on Rows() query against a time field with noStandardView:true 2019-01-14 16:14:45 -06:00
Yuce Tekol
897221a24e
Merge pull request #1824 from yuce/1823-fix-row-range-default-to-updated-docs
fixes #1823. Updates tests and docs for row range
2019-01-15 00:27:20 +03:00
Yuce Tekol
76de81dacf
updated row range test 2019-01-14 23:46:34 +03:00
Yuce Tekol
d75e9eb772
updated row range test 2019-01-14 23:45:58 +03:00
Yuce Tekol
600b39e4e5
updates row range test with a timestamp > the default end timestamp 2019-01-14 23:40:31 +03:00
Yuce Tekol
9f6d489be8
fixes #1823. Updates tests and docs for row range 2019-01-14 14:39:08 +03:00
Travis Turner
01f54c1f70
Merge pull request #1822 from travisturner/range-between-bug
fixes a bug on upper end of bsi range queries
2019-01-11 17:27:28 -06:00
Travis Turner
f7e3296f62
fixes a bug on upper end of bsi range queries 2019-01-11 17:05:29 -06:00
Travis Turner
b0d0105e79
Merge pull request #1818 from travisturner/groupby-filter-test
add a test for groupby filter with RangeLTLT
2019-01-11 16:06:39 -06:00
Travis Turner
0b1fb73b14
add a test for groupby filter with RangeLTLT 2019-01-10 16:56:10 -06:00
Matthew Jaffee
f101cb17b5
Merge pull request #1821 from jaffee/verbose-to-ci-race-tests
add verbose flag to circle ci race test to help debug timeout
2019-01-10 16:36:49 -06:00
Matt Jaffee
93b6048263
add verbose flag to circle ci race test to help debug timeout 2019-01-10 16:12:54 -06:00
Seebs
07674d859c setValue test and benchmark updates
This provides a simple benchmark that can be used for
setValue, to give a way to compare results from adding BSI
support to roaring. Use the BSIGroup prefix for the
fragments, and specify a cache type of "none", to prevent
the use of a LRU cache (which makes things more expensive).

Add a parallel benchmark for ImportValue, so we can compare
them. (Unsurprisingly, the bulk-import endpoint is quite a
lot faster.)

Also, add a test for clearing values to the TestFragment_Sum
test; it turns out that this was never tested in this code,
but the http client test would test it and verify it, it should
probably also be tested here.
2019-01-10 12:07:04 -06:00
Travis Turner
7f6f9be88e
Merge pull request #1817 from travisturner/issue-template
reverse the order of items in the github issue template
2019-01-10 11:06:45 -06:00
Travis Turner
acbe285278
Merge branch 'master' into issue-template 2019-01-10 10:53:59 -06:00
Travis Turner
4e7a3feee2
Merge pull request #1804 from benbjohnson/deprecate-range
Merge Range() into Row() call.
2019-01-10 09:40:13 -06:00
Travis Turner
d1e938ef1a
provide friendlier prompts 2019-01-10 08:07:48 -06:00
Travis Turner
e949a79d34
reverse the order of items in the github issue template 2019-01-09 17:12:49 -06:00
Ben Johnson
9d1e5ca8ce
Merge Range() into Row() call.
This commit refactors the `Range()` call and merges its functionality
into the `Row()` call.
2019-01-09 15:10:49 -07:00
Matthew Jaffee
1726e24aa7
Merge pull request #1814 from jaffee/disable-syncer-if-replicaN-1
disable anti-entropy if not using replication [performance]
2019-01-08 08:28:11 -06:00
Matt Jaffee
af26473f77
disable anti-entropy if not using replication (there will never be anything to sync) 2019-01-07 16:52:43 -06:00
Travis Turner
8c4b1548bc
Merge pull request #1812 from travisturner/error-message
fix incorrect error message
2019-01-04 08:30:02 -06:00
Travis Turner
7db655cb8c
fix incorrect error message 2019-01-04 08:23:19 -06:00
Yuce Tekol
a8da1363cb
Merge pull request #1811 from yuce/public-proto-remove-bit-add-fieldrow-rowkey
Adds tests for GroupBy with keys; removes unused Bit message from proto
2019-01-04 02:09:00 +03:00
Yuce Tekol
c30b03df14
trivial 2019-01-04 01:56:10 +03:00
Yuce Tekol
2babb3c51c
trivial 2019-01-04 01:54:05 +03:00
Yuce Tekol
08b22da8c9
Merge branch 'master' into public-proto-remove-bit-add-fieldrow-rowkey 2019-01-03 15:48:09 +03:00
Yuce Tekol
65c30283d7
adds tests for GroupBy with keys; removes unused Bit message from proto 2019-01-03 15:20:02 +03:00
Matthew Jaffee
2b14c64cbe
Merge pull request #1803 from jaffee/group-by-skip-0
Group by skip 0
2019-01-02 15:13:15 -06:00
Matt Jaffee
5b14227e08
convert gotos to for loops 2019-01-02 14:32:59 -06:00
Todd Gruben
8b06ed9594
removed some debug 2019-01-02 14:32:59 -06:00
Todd Gruben
216fd0964a
a quicker empty check for group by 2019-01-02 14:32:59 -06:00
Matt Jaffee
aa0d64047d
add horrifying code to skip rows with count 0 in Group By 2019-01-02 14:32:59 -06:00
Matthew Jaffee
25f83cedc2
Merge pull request #1802 from jaffee/group-by-fixes
Group by fixes
2018-12-31 17:04:43 -06:00
Matt Jaffee
ed637e6921
add test for group by with invalid filter 2018-12-21 17:24:44 -06:00
Matt Jaffee
81d08be044
fix PQL, Rows and Group By problems
make sure that args which are Uints are positive and return an error if not.

improve group by error messages if field for Rows query is invalid
2018-12-21 14:16:55 -06:00
Matt Jaffee
19696e3085
add GroupBy and Rows docs 2018-12-21 11:56:05 -06:00
Matt Jaffee
97eb94397f
fix Rows bug where Pilosa would crash without 'field' argument. 2018-12-21 11:55:25 -06:00
Matthew Jaffee
03983255ba
Merge pull request #1794 from jaffee/release-v1.2.0
Release v1.2.0
2018-12-20 11:42:45 -06:00
Matt Jaffee
1ebe68fd18
code review fixup for changelog 2018-12-20 11:13:00 -06:00
Matt Jaffee
100cabf8f2
add final change to the changelog 2018-12-20 10:54:37 -06:00
Matt Jaffee
fc09b180c3
fix a bunch of changelog stuff post-review 2018-12-20 10:43:27 -06:00
Matt Jaffee
78ba259d26
Release v1.2.0 2018-12-20 10:43:26 -06:00
Matthew Jaffee
b2ca5f1f26
Merge pull request #1795 from jaffee/close-client-responses
Ensure internal client closes all response bodies
2018-12-20 10:41:27 -06:00
Matt Jaffee
31ab3d37b8
add stress tests
these produce an issue on master, but it is fixed on this branch
2018-12-19 17:21:57 -06:00
Matt Jaffee
ff800131cb
ensure internal client closes all response bodies to avoid leaking connections/goroutines 2018-12-19 11:57:47 -06:00
Matthew Jaffee
4a2ab774d0
Merge pull request #1789 from WaaX/patch-2
Removed the mention of measurements
2018-12-18 14:02:18 -06:00
Matthew Jaffee
4766fa702c
Merge branch 'master' into patch-2 2018-12-18 13:46:55 -06:00
Travis Turner
0a24ab6cb0
Merge pull request #1787 from travisturner/translate-read-buffer-increase
allow translate log entry buffer to grow
2018-12-18 13:28:30 -06:00
Travis Turner
9e09366247
Merge branch 'master' into translate-read-buffer-increase 2018-12-18 13:14:22 -06:00
Matthew Jaffee
9426acecfe
Merge branch 'master' into patch-2 2018-12-18 12:56:30 -06:00
Matthew Jaffee
232d79009b
Merge pull request #1790 from jaffee/makefile-vendor-fix
add Gopkg.lock as a dependency for vendor target
2018-12-18 12:55:45 -06:00
Travis Turner
358c32a165
add test for translate store buffer growth logic. add max limit to buffer size. 2018-12-18 12:48:20 -06:00
Matt Jaffee
ab34df351d
add Gopkg.lock as a dependency for vendor target 2018-12-18 12:27:32 -06:00
Matthew Jaffee
c1b0a9e2a0
Merge branch 'master' into patch-2 2018-12-18 11:18:16 -06:00
Travis Turner
95f05ca4d0
WIP: allow translate log entry buffer to grow
In the case where a translate log entry contained
many key/id pairs, it was possible for the read
buffer (which was allocated at 65536 bytes) to
fail to handle it. This happened when the serialized
LogEntry was larger than 65536 bytes.

This PR adds logic which returns a custom error called
ErrTranslateReadTargetUndersized notifying the reader
to reallocate a larger read buffer and try the read
again.

TODO:
- [ ] Add a max buffer size check to prevent this from doubling the
buffer size with no limit.
- [ ] Add tests.
2018-12-18 09:26:26 -06:00
Travis Turner
6784ab8ac1
Merge pull request #1785 from travisturner/cluster-resize-fix
Cluster resize fix
2018-12-18 09:25:52 -06:00
WaaX
827e5ea5fc
Removed the mention of measurements
Change `measurements` field to `patients index`
Fix import command by removing `-f measurements`
2018-12-18 09:34:52 -05:00
Travis Turner
ca2241731d
fix tracing message. prevent reallocation of availableShards 2018-12-18 08:34:48 -06:00
Travis Turner
d28170ddc6
Syncs AvailableShards when handling a ResizeInstruction.
There was a situation where availableShards on a new
node were not in sync with the cluster, so queries
following a resize were incorrect.
- Start a one-node cluster.
- Write data to shards 0 and 1
- Start a second node.
In the case where the hash algo was moving shard 0 to
node1, then node1 only knew about shard 0, so queries
to node1 would be incomplete.

This PR modifies the ResizeInstruction message to replace
`Schema` with `NodeStatus` (which contains both `Schema` and
`AvailableShards`). So now when a resize instruction is received,
the receiving node is able to sync its schema and availableShards.
2018-12-18 08:34:48 -06:00
Travis Turner
84fddbc67f
Replace the /fragment/data endpoint to support cluster resizing 2018-12-18 08:34:47 -06:00
Matthew Jaffee
047b5874ee
Merge pull request #1788 from jaffee/1691-existence-namespace
1691 existence namespace
2018-12-17 17:02:12 -06:00
Matt Jaffee
ef7f04c09d
schema endpoint doesn't return internal fields 2018-12-17 16:01:32 -06:00
Matt Jaffee
45cd48c1b7
change exists field to _exists 2018-12-17 15:44:50 -06:00
Matthew Jaffee
506e9a2db7
Merge pull request #1786 from jaffee/remove-client-timeout
revert client Timeout addition
2018-12-14 17:09:52 -06:00
Matt Jaffee
2047ebe377
revert client Timeout addition
suspect that this is somehow causing "cannot assign requested address" bugs for
some users. removing since it wasn't a necessary part of the deadlock fix, but
just seemed like a prudent thing to have.
2018-12-14 11:31:23 -06:00
Matthew Jaffee
a2b3cc4a38
Merge pull request #1773 from benbjohnson/query-cancel
Cancel queries on Context.Done()
2018-12-13 17:17:24 -06:00
Ben Johnson
88c18ca1fe
Cancel queries on Context.Done()
This commit periodicially checks if the context has been cancelled
or if a deadline has been reached. If so, it returns a query-related
error message depending on the cause.
2018-12-12 16:55:44 -07:00
Travis Turner
8fe32d764f
Merge pull request #1774 from richardartoul/ra/fix-union-in-place-bug
Fix bug in UnionInPlace function and add property test
2018-12-12 16:49:30 -06:00
Richard Artoul
e7ca4562ea Fix bug in unionInPlaceImplementation 2018-12-12 14:26:57 -08:00
Matthew Jaffee
6ed5da1714
Merge pull request #1771 from jaffee/import-benchmarking
Import benchmarking
2018-12-12 11:34:48 -06:00
Matt Jaffee
7e90917c3c
suppress linter for init call 2018-12-12 10:26:08 -06:00
Matt Jaffee
f2578c401f
clean up fragments more cleanly (in tests and benchmarks) 2018-12-12 10:26:08 -06:00
Matt Jaffee
4f808c2028
add flag or setting temp dir used for benchmarks 2018-12-12 10:26:08 -06:00
Matt Jaffee
4f459028d9
add concurrent update benchmark and clean up temp frags 2018-12-12 10:26:08 -06:00
Matt Jaffee
054926fd6c
add concurrent import benchmark 2018-12-12 10:26:08 -06:00
Matt Jaffee
dc01dff3d3
add import roaring and import w/update benchmarks 2018-12-12 10:26:07 -06:00
Travis Turner
17ea3f7f94
Merge pull request #1781 from travisturner/test-fix
fixed a mistake in the test from PR 1780
2018-12-11 17:32:17 -06:00
Travis Turner
eadd77f901
fixed a mistake in the test from PR 1780 2018-12-11 16:20:10 -06:00
Matthew Jaffee
2597be4ad5
Merge pull request #1782 from jaffee/cluster-w-replication-deadlock
attempt to fix deadlock by releasing view lock before broadcasting Cr…
2018-12-11 16:16:14 -06:00
Matt Jaffee
9d4a6e2be7
don't add the fragment and then remove it 2018-12-11 15:45:44 -06:00
Matt Jaffee
8b3e5b998a
fix data race which appears to be unrelated to previous changes 2018-12-11 15:45:44 -06:00
Matt Jaffee
7304258967
improve comments 2018-12-11 15:45:44 -06:00
Matt Jaffee
4b786e1057
attempt to fix deadlock by releasing view lock before broadcasting CreateShard 2018-12-11 15:45:44 -06:00
Matthew Jaffee
bb65a4a14f
Merge pull request #1777 from jaffee/1776-unexpected-resizing
fix bug where cluster goes into RESIZING instead of NORMAL
2018-12-11 12:22:24 -06:00
Matt Jaffee
2c4401db8c
hopefully fix data race 2018-12-11 09:22:04 -06:00
Matt Jaffee
7e6c406212
fix bug where cluster goes into RESIZING instead of NORMAL
running
"make clustertests
DOCKER_COMPOSE=internal/clustertests/docker-compose-replication2.yml"

shows this issue (just remove the change in cluster.go).

Also removed two unrelated lines of code that appear to be doing absolutely nothing.
2018-12-11 09:22:03 -06:00
Travis Turner
01e520d9ea
Merge pull request #1780 from travisturner/anti-entropy-roaring
convert the anti-entropy logic to use `ImportRoaring` instead of `QueryNode`
2018-12-10 22:01:26 -06:00
Travis Turner
c66daabc81
convert the anti-entropy logic to use ImportRoaring instead of QueryNode 2018-12-10 21:05:08 -06:00
Matthew Jaffee
69059e91d2
Merge pull request #1779 from pilosa/jaffee-docs-patch
wrap <CALL> in backquotes so it gets displayed.
2018-12-10 18:22:12 -06:00
Matthew Jaffee
9ac4d981fc
wrap <CALL> in backquotes so it gets displayed.
previously was not rendering - I assume because it was being interpreted as an HTML tag.
2018-12-10 17:24:23 -06:00
Travis Turner
fef0b26c89
Merge pull request #1766 from richardartoul/ra/optimize-in-place-bulk
Implement fast roaring bitmap union (Part 1)
2018-12-07 15:52:23 -06:00
Richard Artoul
082c8aba56 switch to |= 2018-12-07 16:13:42 -05:00
Richard Artoul
dcfed6ebb6 fix grammar 2018-12-07 16:11:16 -05:00
Richard Artoul
a11d04c061 clarify comment 2018-12-07 16:11:16 -05:00
Richard Artoul
9da6d43b76 fix docstring nit 2018-12-07 16:11:16 -05:00
Richard Artoul
c495d08d1b simplify logic by removing concept or target 2018-12-07 16:11:16 -05:00
Richard Artoul
5b72544d73 simplify helper with early return 2018-12-07 16:11:16 -05:00
Richard Artoul
bb20f058ba Add Repair operation to btree containers 2018-12-07 16:11:16 -05:00
Richard Artoul
71621e60ba Refactor roaring repair operations 2018-12-07 16:11:16 -05:00
Richard Artoul
34b1f2199f Fix comment 2018-12-07 16:11:16 -05:00
Richard Artoul
3570ec7ab6 collapse next calls into conditonals 2018-12-07 16:11:16 -05:00
Richard Artoul
531b9d616d Refactor code and comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
069c2a281d unroll to make a little faster 2018-12-07 16:11:16 -05:00
Richard Artoul
c412bc595d add benchmark 2018-12-07 16:11:16 -05:00
Richard Artoul
42e756b316 Add benchmark 2018-12-07 16:11:16 -05:00
Richard Artoul
6d021fe870 add comment 2018-12-07 16:11:16 -05:00
Richard Artoul
549595cd2e fix lint issues 2018-12-07 16:11:16 -05:00
Richard Artoul
741f8e8b84 remove repairBitmaps from public iface 2018-12-07 16:11:16 -05:00
Richard Artoul
12d45415bb more refactoring and micro optimizations 2018-12-07 16:11:16 -05:00
Richard Artoul
ddfc95070b rename var 2018-12-07 16:11:16 -05:00
Richard Artoul
7a57b24b46 Fix comment 2018-12-07 16:11:16 -05:00
Richard Artoul
a2bb87771d Refactor 2018-12-07 16:11:16 -05:00
Richard Artoul
d96bde179d factor out summary stats calculation into helper 2018-12-07 16:11:16 -05:00
Richard Artoul
3d0d0db2e9 more micro-optimizations 2018-12-07 16:11:16 -05:00
Richard Artoul
76aea6d9bc rename structs 2018-12-07 16:11:16 -05:00
Richard Artoul
c1c1121e51 more comment refactoring 2018-12-07 16:11:16 -05:00
Richard Artoul
5ddeb0f6a0 refactor comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
d35aabfa86 remove double space 2018-12-07 16:11:16 -05:00
Richard Artoul
d6e2d07687 refactor comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
3193fc98ab refactor comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
3f3fec3824 refactor comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
efd6116d3f replace word in comment for clarity 2018-12-07 16:11:16 -05:00
Richard Artoul
038e3d4304 fix diagram 2018-12-07 16:11:16 -05:00
Richard Artoul
f97ff4b5a0 special case individual union 2018-12-07 16:11:16 -05:00
Richard Artoul
56b3d7d5db fix comment 2018-12-07 16:11:16 -05:00
Richard Artoul
feb19c62b9 Change repair functions to specify they are bitmap only 2018-12-07 16:11:16 -05:00
Richard Artoul
25eae0204d Update benchmarks 2018-12-07 16:11:16 -05:00
Richard Artoul
70338be7ca Add crazy comment 2018-12-07 16:11:16 -05:00
Richard Artoul
49df3fcd30 Dont shadow statshit 2018-12-07 16:11:16 -05:00
Richard Artoul
4cdf2adbe5 fix comment 2018-12-07 16:11:16 -05:00
Richard Artoul
06e7dbdc75 simplify and remove dead code 2018-12-07 16:11:16 -05:00
Richard Artoul
7931bc2c37 Add comment 2018-12-07 16:11:16 -05:00
Richard Artoul
defcb40f8c Add comment 2018-12-07 16:11:16 -05:00
Richard Artoul
c02479a5f9 more comments and cleanup 2018-12-07 16:11:16 -05:00
Richard Artoul
8e3da346c3 Add more comments and add helper method for bulk marking handled 2018-12-07 16:11:16 -05:00
Richard Artoul
5b50ecfd8e delete unused code 2018-12-07 16:11:16 -05:00
Richard Artoul
13dbe22b18 Move next logic into helper 2018-12-07 16:11:16 -05:00
Richard Artoul
fccc707006 remove debug code 2018-12-07 16:11:16 -05:00
Richard Artoul
d78e2fc87c Move repair logic to helpers 2018-12-07 16:11:16 -05:00
Richard Artoul
50f119df4e Allocate bitmap if needed (existing wrong type 2018-12-07 16:11:15 -05:00
Richard Artoul
3eb060c4c6 fix bug 2018-12-07 16:11:15 -05:00
Richard Artoul
eb5ad7bf49 dont keep n in sync with bitmaprun in place 2018-12-07 16:11:15 -05:00
Richard Artoul
b47292aa26 switch to bitmap repairs for inplace algo 2018-12-07 16:11:15 -05:00
Richard Artoul
339a78d88d wokring 2018-12-07 16:11:15 -05:00
Richard Artoul
e8e4369f76 all passing 2018-12-07 16:11:15 -05:00
Richard Artoul
30946a0372 working 2018-12-07 16:11:15 -05:00
Richard Artoul
af3cb91a40 first 2018-12-07 16:11:15 -05:00
Richard Artoul
2e1f60ac42 horrible wip 2018-12-07 16:11:15 -05:00
Richard Artoul
d2da91fdde add test 2018-12-07 16:11:15 -05:00
Richard Artoul
d3606e274d fix bug 2018-12-07 16:11:15 -05:00
Richard Artoul
b77c8a630b Add in place union 2018-12-07 16:11:15 -05:00
Yuce Tekol
82a9ef2059 Added /internal/translate/keys endpoint 2018-12-07 16:11:15 -05:00
Ben Johnson
daee7caed5
Merge pull request #1753 from benbjohnson/group-by-filter
Add GroupBy() Filter
2018-12-07 11:21:08 -07:00
Ben Johnson
727659644b
Add GroupBy filter. 2018-12-07 10:35:57 -07:00
Matthew Jaffee
73e07ae11e
Merge pull request #1769 from jaffee/state-down-fix
propogate updates to node details (not just additions and deletions)
2018-12-04 18:29:15 -06:00
Matt Jaffee
ef6db5cc1a
propogate updates to node details (not just additions and deletions)
to all nodes in cluster, not just coordinator
2018-12-04 14:03:14 -06:00
Cody Soyland
dfb748ec5b
Merge pull request #1764 from codysoyland/arm64-support
Fix arm64 support
2018-11-30 11:12:12 -06:00
Cody Soyland
53dfccbde4
Merge branch 'master' into arm64-support 2018-11-30 11:05:04 -06:00
Yuce Tekol
4c14e5be35
Merge pull request #1751 from yuce/translate-keys-endpoint
Added /internal/translate/keys endpoint
2018-11-28 22:51:37 +03:00
Yuce Tekol
66770d5bfb
Merge branch 'master' into translate-keys-endpoint 2018-11-28 22:06:11 +03:00
Cody Soyland
7330daa222 Add ARM build to CI 2018-11-27 11:14:47 -06:00
Cody Soyland
f0c6394c61 Use syscall.Dup3 on ARM64 as Dup2 is unsupported 2018-11-27 11:03:59 -06:00
Todd Gruben
de1b9b4de2 yata gofmt 2018-11-26 15:21:37 -06:00
Todd Gruben
ba0ad350a9 Merge branch 'shift-op' of github.com:tgruben/pilosa into shift-op 2018-11-26 15:06:33 -06:00
Todd Gruben
f6d34b42ba gofmt 2018-11-26 15:05:43 -06:00
Seebs
3f6c17f433 roaring: use DirectAdd rather than op.apply for cheap performance win
Calling op.apply on an op we know to be an add ends up noticably
increasing the cost of the operation; this trivial change gets about
a 5-10% reduction in reported runtime of benchmarks doing a lot
of adds. (The other IntersectionCount benchmarks don't actually use
Add most of the time, so it doesn't show up in them.)

name                                    old time/op  new time/op  delta
GetBenchData-8                          4.25ms ± 0%  3.91ms ± 2%   -8.04%  (p=0.002 n=6+6)
Bitmap_IntersectionCount_ArrayArray-8   20.9µs ± 2%  18.7µs ± 3%  -10.18%  (p=0.004 n=5+6)
SliceAscending-8                        24.7ms ± 0%  21.8ms ± 0%  -11.74%  (p=0.004 n=5+6)
SliceDescending-8                       29.8ms ± 0%  27.0ms ± 0%   -9.56%  (p=0.004 n=5+6)
SliceAscendingStriped-8                 32.0ms ± 0%  29.5ms ± 0%   -8.07%  (p=0.008 n=5+5)
SliceDescendingStriped-8                39.3ms ± 1%  36.8ms ± 1%   -6.27%  (p=0.002 n=6+6)
2018-11-26 14:12:02 -06:00
Seebs
67e3dc4a08 roaring: improve SliceAscending/SliceDescending tests
Two changes: First, make SliceDescending set the entire
slice, not all-but-one bits. Second, add tests that are
"striped", so it's writing to 8 parts of the slice
sequentially, rather than just going up or down the whole
thing, because that gives us some cheap indication of
cache-locality impact, which turns out to be possibly
significant.
2018-11-26 14:12:02 -06:00
tgruben
dc8f0a430b
Merge branch 'master' into shift-op 2018-11-26 11:55:57 -06:00
Todd Gruben
0404354faa add shift operater to pql 2018-11-26 11:29:05 -06:00
Cody Soyland
d5b4197793
Merge pull request #1756 from codysoyland/circleci-go-1.11-race
CircleCI: Add race detector to parallel build. Default to Go 1.11.
2018-11-26 09:14:35 -06:00
Cody Soyland
31d6e8ebba CircleCI: Add race detector to parallel build. Default to Go 1.11. 2018-11-26 09:00:53 -06:00
Cody Soyland
ed79589aad
Merge pull request #1755 from codysoyland/makefile-simplify-require
Simplify "require-*" logic in Makefile
2018-11-26 08:53:03 -06:00
Yuce Tekol
d543689868
updated translate keys test to include new keys 2018-11-26 17:52:53 +03:00
Cody Soyland
6b901fdc0b Simplify "require-*" logic in Makefile 2018-11-26 08:46:24 -06:00
Yuce Tekol
eb9e609794
Merged with master 2018-11-26 17:03:38 +03:00
Ben Johnson
3673636902
Merge pull request #1684 from benbjohnson/tracing
Add distributed tracing.
2018-11-21 14:53:20 -07:00
Cody Soyland
6dc7ec3386 Add docs 2018-11-21 15:14:06 -06:00
Cody Soyland
983f7c95af Add flag --tracing.agent-host-port 2018-11-21 15:08:33 -06:00
Ben Johnson
8e49332b25 Add distributed tracing. 2018-11-21 15:08:33 -06:00
Yuce Tekol
ef21492ae0
Merge pull request #1733 from yuce/1710-suppress-std-view-on-time-fields
Adds NoStandardView field option. Fixes #1710
2018-11-21 18:54:04 +03:00
Yuce Tekol
81354461a0
Merge branch 'master' into 1710-suppress-std-view-on-time-fields 2018-11-21 18:44:29 +03:00
Yuce Tekol
2447b5df1b
Merge pull request #1738 from yuce/1716-roaring-import-for-time-fields
Import roaring endpoint accepts a list of views
2018-11-21 18:43:46 +03:00
Yuce Tekol
12112e0aef
Merged with master; check for empty roaring data 2018-11-21 18:22:40 +03:00
Yuce Tekol
ac91635628
Merged with master 2018-11-21 18:16:43 +03:00
Yuce Tekol
d9c158445d
add OptFieldTypeTime comment 2018-11-21 18:12:00 +03:00
Yuce Tekol
2c91bf69b3
Merge branch 'master' into translate-keys-endpoint 2018-11-21 16:38:23 +03:00
Yuce Tekol
9c05155db4
Added /internal/translate/keys endpoint 2018-11-21 16:35:50 +03:00
Yuce Tekol
1faa789b31
remove ImportRoaringRequestView type 2018-11-21 14:53:16 +03:00
Todd Gruben
933d5e28e7 initial bit shift functions for all container type 2018-11-20 15:12:02 -06:00
Matthew Jaffee
ab7a833019
Merge pull request #1750 from jaffee/more-races
More races
2018-11-20 14:50:59 -06:00
Matt Jaffee
e1adb8ce5f
fix view.createFragment race 2018-11-20 14:21:37 -06:00
Matt Jaffee
5458eb1656
fix holder.opened race with absurd lockedChan 2018-11-20 14:21:36 -06:00
Matthew Jaffee
c417396502
Merge pull request #1749 from jaffee/1746-checksums-race
fix fragment checksums race condition
2018-11-20 14:21:14 -06:00
Yuce Tekol
3d54f737cd
ditch OptFieldTypeTimeWithOptions 2018-11-20 23:21:09 +03:00
Matt Jaffee
8bc1104585
fix fragment checksums race condition 2018-11-20 14:16:23 -06:00
Matthew Jaffee
6e58c9d046
Merge pull request #1748 from jaffee/logging-cleanup
Logging cleanup
2018-11-20 14:14:29 -06:00
Matt Jaffee
77598c2cc6
dup log output onto stderr to catch panics in log file 2018-11-20 14:08:07 -06:00
Matt Jaffee
65f478470f
logging cleanup - start with lowercase unless reporting error or warning 2018-11-20 14:08:06 -06:00
Yuce Tekol
9043b78a65
Merge pull request #1732 from yuce/import-cmd-field-type-flag
Import cmd field type flag
2018-11-20 21:28:15 +03:00
Yuce Tekol
fd435f2806
Merge branch 'master' into import-cmd-field-type-flag 2018-11-20 21:19:28 +03:00
Yuce Tekol
46c22a101f
updated protobuf generated files 2018-11-20 19:01:20 +03:00
Travis Turner
e472ed3984
Merge pull request #1744 from travisturner/translate-file-size
increase the translate file size for tests/benchmarks
2018-11-19 11:47:11 -06:00
Travis Turner
c8ac958360
Merge branch 'master' into translate-file-size 2018-11-19 11:43:42 -06:00
seebs
0ed5b86315
Merge pull request #1741 from seebs/seebs/bench
import benchmark changes and updates to improve utility of benchmarks so we can submit some relevant benchmarks to the go compiler wiki.
2018-11-16 16:40:09 -06:00
Seebs
e20671b2b4 silence gometalinter
I am aware that I don't actually ever use the length of a
after this line of code, but if I don't correctly update it,
any future change that needs that length will break
mysteriously. We humbly ask gometalinter to consider
the reply of counsel in _Arkell v. Pressdram_ (1971).
2018-11-16 15:00:09 -06:00
Seebs
7c82f48046 improve testing for intersections of array/array pairs
A transient bug introduced in intersectionCountArrayArray was
not caught by the tests, because it would only manifest when
two containers of different lengths were being compared. Also
improve the testing for intersectArrayArray, even though that
code hasn't been changed.
2018-11-16 15:00:09 -06:00
Seebs
1a8633f3a5 use roaring conventions for variable names
Roaring likes to call things "a" and "b", not "1" and "2",
and use "n" for length, not "l", etcetera. Adopt these
conventions to make code more readable.

Also drop the 'vb' value since it isn't expensive to
compute and the compiler can figure out that it can
reuse the value.
2018-11-16 15:00:09 -06:00
Seebs
9b552ab508 enhance TestRunCountRange
confirm that the number of runs comes out as expected,
and add a couple of numbers out of order to verify that
the 17-18-19 set gets coalesced into one run even
if we add 17 and 19 before 18.
2018-11-16 14:59:46 -06:00
Seebs
d4364bea52 slightly streamline array/array comparison
The net effect of this is to not recompute "the current
value of the first array" on every loop, pretty much.
However, the swap to make sure the inner loop is on the
longer array seems to be significant for performance.
On my system, this moves runtime from ~29us per op
to ~17us per op.
2018-11-16 14:59:46 -06:00
Seebs
32c4b3540f simplify intersectBitmapRun output to remove a conversion
If the total number of things returned was small enough to
make an array, intersectBitmapRun converted to an array. This
seems possibly-premature; future processing might well prefer
a bitmap. We know everything gets optimized before being
written out, let's not convert without a specific reason. But
also, let's use an array no matter which container is small
enough to prove that we can do so safely.

Fixes #854.
2018-11-16 14:59:09 -06:00
Seebs
c8e6fd2e43 improve type matrix for IntersectionCount benchmarks
The circumstances under which bitmaps are converted between
types are not 100% nailed down, and the IntersectionCount
benchmark was actually using a bitmap for the "run" data set
as well as for the "bitmap" data set. Fix that by using
Optimize() explicitly. Also, add a second RLE set so we
can compare the difference between "one run for the entire
set" and "several runs".

Also add array/array comparisons. We use two different
lengths of arrays, because performance turns out to vary
between "first array longer" and "second array longer".

Also added a benchmark for getBenchData itself, since it's
at least one possible use case for "creating a lot of
containers".
2018-11-16 14:59:09 -06:00
Travis Turner
08d7f65667
increase the translate file size for tests/benchmarks 2018-11-16 13:01:21 -06:00
seebs
377abb22c2
Merge pull request #1743 from seebs/seebs/stats
add some stat tracking to roaring/ implementation.
2018-11-16 10:02:00 -06:00
Seebs
8e270f9201 provide commented-out test case for bug in dead code
bitmapEquals isn't currently being called ever, but it has
an arcane edge-case bug, so I've made the test case for it
and commented it out for future reference.
2018-11-15 15:11:08 -06:00
Seebs
33add4f1e0 proof of concept for stats
This commit adds some trivial stat-tracking which can be
observed at localhost:10101/debug/vars. However, writes to
a locking data structure aren't cheap, so the stat-tracking
is by default not compiled. To build it, add the build
tag `roaringstats`, which will cause the `statsHit` function
to actually do something. Otherwise, it's an empty and
inlineable function, meaning the compiler throws it away
entirely.

This would, in principle, let us get additional visibility
into edge cases and which code paths are hot. This is not
the same thing as profiling for overall performance; the
stat counts aren't affected by whether a particular code path
is using a large amount of CPU time, just reporting how
often it happens at all.
2018-11-15 15:10:48 -06:00
Seebs
a203313143 move Logger and Stats to their own packages
I'd like to add stat tracking to Roaring, which means it
has to be able to import the stats package, which means
stats has to be a package rather than part of the pilosa
package. If stats stops being in pilosa, it still needs
a way to import logger, so logger also has to leave the
pilosa package. Then everything using them needs to import
them and use package selectors on their names.

This doesn't actually add the stats support to roaring,
it just makes it so there's a way to import the stats
code from something in the roaring package.
2018-11-15 15:10:44 -06:00
Yuce Tekol
84148d4ee6
Merge pull request #1742 from yuce/fix-unmarshal-bitmap-with-empty-data
Prevent panic in Bitmap.UnmarshalBinary when there is no data
2018-11-15 22:21:38 +03:00
Yuce Tekol
70f85211d9
prevent panic in Bitmap.UnmarshalBinary when there is no data 2018-11-15 22:06:21 +03:00
Yuce Tekol
0fe5d56f68
Merged with master 2018-11-15 21:19:58 +03:00
Yuce Tekol
2bab6eb5ec
enable roaring import for time fields; build view name 2018-11-14 16:31:09 +03:00
Cody Soyland
faac64dc99
Merge pull request #1740 from codysoyland/circleci-shield
Remove TravisCI, add CircleCI shield
2018-11-13 13:28:45 -06:00
Cody Soyland
1cd7ebdd2c Remove TravisCI, add CircleCI shield 2018-11-13 12:34:44 -06:00
Matthew Jaffee
49b75aef69
Merge pull request #1717 from jaffee/cluster-tests
Cluster tests
2018-11-13 12:10:54 -06:00
Matt Jaffee
a9d108200b
update circle ci config with cody's feedback 2018-11-13 11:52:08 -06:00
Matt Jaffee
08431f6e76
iterate on ci config 2018-11-13 09:53:44 -06:00
Matt Jaffee
26cd503393
try to run clustertests in CI 2018-11-13 09:51:22 -06:00
Matt Jaffee
bc8b991220
rename Dockerfile-withgo to Dockerfile-clustertests 2018-11-13 09:31:16 -06:00
Matt Jaffee
0d4a46af97
use internal client instead of go-pilosa, use ADD instead of wget 2018-11-13 09:24:35 -06:00
Matt Jaffee
37ac8b7a93
better use of docker-compose opts per code review 2018-11-12 17:44:23 -06:00
Matt Jaffee
90c5f64b19
filter memberlist debug and info logs, use t.Log instead of fmt in cluster tests 2018-11-12 14:01:57 -06:00
Yuce Tekol
1642e22872
fixed handler tests 2018-11-12 19:24:32 +03:00
Yuce Tekol
84c04900e1
Import roaring enpoint accepts a list of views 2018-11-12 18:43:59 +03:00
Matt Jaffee
9c9b1c5afe
Merge branch 'master' into cluster-tests 2018-11-09 12:23:21 -06:00
Matt Jaffee
8cd53bf2c2
Revert "msg type stringer"
This reverts commit dd4685d43b.
2018-11-09 11:34:32 -06:00
Matt Jaffee
dd4685d43b
msg type stringer 2018-11-09 11:28:53 -06:00
Matt Jaffee
deae8ce7c0
improvements to clustertests and fix cluster pause bug by state sharing 2018-11-09 11:28:19 -06:00
Yuce Tekol
8c99bd7a15
Merge pull request #1737 from yuce/remove-unused-rule-from-peg
Removed unused rule from peg grammar
2018-11-09 16:34:02 +03:00
Yuce Tekol
44e436f571
removed unused rule from peg grammar 2018-11-09 08:08:43 +03:00
Yuce Tekol
45e2951e87
fix GML warning 2018-11-08 20:48:56 +03:00
Yuce Tekol
745ec43432
fixes f.SetBit 2018-11-08 20:40:57 +03:00
Yuce Tekol
7913a419ae
adds NoStandardView field option. Fixes #1710 2018-11-08 18:33:39 +03:00
Yuce Tekol
27c222f02d
Refactored missing executeRequest bits; check resp is not nil 2018-11-08 17:02:07 +03:00
Yuce Tekol
fc231ff802
Fixes #1731 2018-11-08 17:01:05 +03:00
Yuce Tekol
8e58fe3541
Merge pull request #1729 from yuce/1697-internal-client-error-report
Improve Internal Client errors. Fixes #1697
2018-11-08 16:23:35 +03:00
Yuce Tekol
f2394f6d93
lowercase error msg 2018-11-08 08:25:43 +03:00
Yuce Tekol
7b7e96bdee
Trivial 2018-11-07 18:47:15 +03:00
Yuce Tekol
8d5f76d4f4
Fixes #1697 2018-11-07 18:37:28 +03:00
Yuce Tekol
2416d7a4c0
Merge pull request #1727 from yuce/allow-backslash-cr-in-pql-strings
fix double escapes
2018-11-07 01:25:59 +03:00
Yuce Tekol
cad9d83c40
fix double escapes 2018-11-07 01:10:58 +03:00
Yuce Tekol
997f448ef5
Merge pull request #1713 from yuce/allow-backslash-cr-in-pql-strings
Allow backslash, carriage return in PQL strings
2018-11-06 23:58:49 +03:00
Yuce Tekol
0c0709eb20
Merge branch 'master' into allow-backslash-cr-in-pql-strings 2018-11-06 23:28:57 +03:00
Travis Turner
0dbd8738df
Merge pull request #1725 from travisturner/upgrade-peg
upgrade peg at: github.com/pointlander/peg
2018-11-06 14:16:19 -06:00
Yuce Tekol
6cdfafc257
Merge branch 'master' into allow-backslash-cr-in-pql-strings 2018-11-06 23:16:13 +03:00
Travis Turner
5b30393bc9
upgrade peg at: github.com/pointlander/peg 2018-11-06 14:12:06 -06:00
Travis Turner
89f0c82e01
Merge pull request #1724 from travisturner/upgrade-protoc
upgrade to protoc 3.6.1. (also updated protoc-gen-gofast).
2018-11-06 14:11:28 -06:00
Travis Turner
be202a61a7
upgrade to protoc 3.6.1. (also updated protoc-gen-gofast). 2018-11-06 14:01:09 -06:00
Yuce Tekol
1e30a9372d
Disabled unquoting for single quoted attribute values; updated test 2018-11-06 22:58:37 +03:00
Yuce Tekol
e9c1606a9d
Merge branch 'master' into allow-backslash-cr-in-pql-strings 2018-11-06 22:49:28 +03:00
Yuce Tekol
b158f1c378
unquote attribute values 2018-11-06 22:47:09 +03:00
alanbernstein
2e7d44ba29
Merge pull request #1722 from pilosa/minor-docs-updates
Minor docs updates
2018-11-06 11:43:29 -06:00
alanbernstein
7e6a2e41f6
Merge branch 'master' into minor-docs-updates 2018-11-06 11:30:13 -06:00
Yuce Tekol
56ee728724
Merge branch 'master' into allow-backslash-cr-in-pql-strings 2018-11-06 14:12:36 +03:00
Yuce Tekol
2a8f2c2026
minor grammar fix 2018-11-06 14:09:32 +03:00
Travis Turner
2ddde5fac6
Merge pull request #1719 from travisturner/import-shard-forward
forward imports to non-coordinator shards
2018-11-05 21:49:06 -06:00
Travis Turner
063caed8d1
forward imports to non-coordinator shards 2018-11-05 17:39:42 -06:00
Alan Bernstein
be5f8c923d Remove 'view' from nav 2018-11-05 12:34:08 -06:00
seebs
dde7551b88
Merge pull request #1712 from seebs/seebs/btree
Ensure btree comparison doesn't fail for smallish N

(Which is to say, differences between values exceeding the max value
of int.)
2018-11-05 11:53:41 -06:00
Alan Bernstein
497c541aff Remove outdated anchor link 2018-11-05 11:37:03 -06:00
Alan Bernstein
100c780704 Switch data model diagrams to png 2018-11-05 11:36:55 -06:00
Seebs
456c092930 enterprise/b: Ensure 64-bit range for btree keys.
The cmp() function used to compare btree keys was using the
trick of comparing unsigned values by coercing the result
of subtraction to a signed type. This is fine as long as
the range of differences never actually exceeds the limits
of the signed type. For instance, with int64, as long as
the magnitude of the difference is under 2^63 or so, it
works reasonably well.

Plain int, however, can be a 32-bit type, at which point
the magnitude of difference needed to break it is only
2^31 or so.

Subtraction and type conversion is enough cheaper than
branches that this is worth preserving, but it's worth
preserving by switching to an explicit int64 for the
operation and return type. This will not actually affect
performance except for people using the btree code on
32-bit machines, so it probably won't ever matter.
Which may also be true of the potential wrong answers,
but "might be slower" is a better risk than "might
crash".
2018-11-05 10:45:17 -06:00
seebs
3a2c2c227d
Merge pull request #1711 from seebs/seebs/method
Drop now-superfluous methodNotAllowedHandler
2018-11-05 09:38:05 -06:00
Matt Jaffee
6d821afed9
add note on skipped cluster test 2018-11-02 16:13:03 -05:00
Matt Jaffee
ec3982c0ff
pull out advertise URI changes 2018-11-02 16:10:39 -05:00
Matt Jaffee
02aee931a1
few small fixes 2018-11-02 16:03:50 -05:00
Matt Jaffee
d86e9ed3ea
add docker based cluster tests, remove proxy stuff, fix advertise 2018-11-02 14:41:42 -05:00
Yuce Tekol
3cb3a065dd
allow backlash, carriage return in pql strings 2018-11-01 21:56:34 +03:00
Seebs
ce815471fe Drop now-superfluous methodNotAllowedHandler
Long ago, the maintainers of gorilla/mux concluded that
it was a "wontfix" to return StatusMethodNotAllowed instead
of StatusNotFound for a method mismatch. Pilosa had a
workaround for this for the most common case (GET requests
to /index/{index}/query), and a TODO to address the other
cases.

While browsing the go-pilosa client code, I noticed that there
is a test for roaring import support which relies on getting
StatusMethodNotAllowed.  But how can this work, if gorilla/mux
doesn't do that?

Answer: They started doing it in mid-2017, apparently:
	https://github.com/gorilla/mux/issues/271

Dropping this code changes the exact text of the message
produced for that one case, but not the status code,
and makes the behavior less confusing.
2018-11-01 12:59:58 -05:00
Matthew Jaffee
5d99f70589
Merge pull request #1707 from dene14/docker-extra-tools
Add base system, curl and jq for debug and checks.
2018-10-31 09:34:40 -05:00
Denis Boulas
e80d5c5e56 Add base system, curl and jq for debug and checks. 2018-10-27 03:20:43 +03:00
Matt Jaffee
ec08930c30
Merge branch 'master' into cluster-tests 2018-10-26 16:14:00 -05:00
Matt Jaffee
62c1bfe90e
implement MustNewClusterWithProxy and drop/undrop for partitioning 2018-10-26 16:13:20 -05:00
Matt Jaffee
af7ece74fd
test drop and undrop in udproxy. 2018-10-26 09:17:26 -05:00
Matthew Jaffee
0fc08c696a
Merge pull request #1647 from jaffee/new-rows-iterate
copy non roaring-import code from Todds's row-iterate PR
2018-10-25 09:49:48 -05:00
Matt Jaffee
a0f4522b6a
fix up linter issues in new groupby/rows tests 2018-10-25 08:35:09 -05:00
Matt Jaffee
30590c83bd
Merge branch 'master' into new-rows-iterate 2018-10-25 08:14:58 -05:00
Matt Jaffee
21c35e6861
wrap errors, fix comment, add test 2018-10-24 17:18:39 -05:00
Matt Jaffee
671420f31d
add custom json marshal for FieldRow 2018-10-24 17:11:45 -05:00
Matt Jaffee
28591b4a91
WIP: figure out why config.Gossip.Port is 0 after cluster start 2018-10-24 16:56:32 -05:00
Matt Jaffee
f643487ce0
add initial UDP proxy code to support proxying/partitioning memberlist 2018-10-24 16:56:07 -05:00
Travis Turner
79bf01f79a
Merge pull request #1699 from travisturner/import-clear
add `clear` functional option for imports
2018-10-24 16:15:49 -05:00
Travis Turner
e69a8f3db4
handle clear flag on import roaring (http package) 2018-10-24 15:16:08 -05:00
Travis Turner
f02605a528
consolidate ImportOptions setup. use url.Values{}. fix comments. 2018-10-23 17:37:57 -05:00
Travis Turner
318e588b4d
document the --clear flag for imports 2018-10-23 17:37:57 -05:00
Travis Turner
f29b6e79ff
add import clear test coverage to http package 2018-10-23 17:37:57 -05:00
Travis Turner
5fb6ef224c
add clear support for ImportRoaring 2018-10-23 17:37:57 -05:00
Travis Turner
a7a15c64a2
support clear imports to int fields. fix bug in fragment.sum 2018-10-23 17:37:57 -05:00
Travis Turner
caf8e06712
add clear functional option for imports 2018-10-23 17:37:57 -05:00
Matthew Jaffee
dc3fbe4afa
Merge pull request #1700 from jaffee/import-docs
add more import docs
2018-10-23 14:32:52 -05:00
Matt Jaffee
0ab3ee7c73
Merge remote-tracking branch 'origin/master' into import-docs 2018-10-23 14:23:18 -05:00
Matt Jaffee
376c2d61ff
address CR feedback 2018-10-23 13:50:35 -05:00
Yuce Tekol
d127a83b1e
Merge pull request #1698 from yuce/1680-update-api-docs
Updated API docs
2018-10-23 21:46:17 +03:00
Matthew Jaffee
4eed160b2d
wip on adding import docs 2018-10-23 11:49:55 -05:00
Matt Jaffee
8db7a78a93
unpushed WIP on cluster-tests 2018-10-23 11:10:24 -05:00
Matthew Jaffee
ad26eeca1b
Merge pull request #5 from travisturner/new-rows-iterate-translated
translate column argument in Rows() query
2018-10-23 08:19:52 -05:00
Travis Turner
9fee746e76
translate column argument in Rows() query 2018-10-22 17:41:59 -05:00
Yuce Tekol
5060e6ee47
updated 2018-10-22 17:24:21 +03:00
Yuce Tekol
f2c096040a
updated api docs 2018-10-22 15:47:29 +03:00
Matt Jaffee
63b3954117
Merge branch 'master' into new-rows-iterate 2018-10-18 14:37:28 -05:00
Matt Jaffee
f9dbacf332
fix compile errors 2018-10-18 14:36:44 -05:00
tgruben
05211bdf70
Merge pull request #1674 from tgruben/fix-logger
converted to pilosa.logger
2018-10-17 18:57:52 -05:00
tgruben
ba00794683
Merge branch 'master' into fix-logger 2018-10-17 18:12:35 -05:00
Travis Turner
079d615c80
Merge pull request #1675 from travisturner/create-fragment-error
ensure view closes fragment on broadcast error
2018-10-17 18:12:20 -05:00
Travis Turner
cdcbb6ed61
Merge branch 'master' into create-fragment-error 2018-10-17 18:10:00 -05:00
Travis Turner
ddd0b7648a
Merge pull request #1696 from travisturner/test-verbose-stderr
prevent closing os.Stderr (used in verbose test logging)
2018-10-17 18:06:09 -05:00
Travis Turner
42531f72fb
prevent closing os.Stdout or os.Stderr (used in verbose test logging) 2018-10-17 17:59:57 -05:00
Todd Gruben
764fc90e58 Merge remote-tracking branch 'upstream/master' into fix-logger 2018-10-17 17:59:09 -05:00
Todd Gruben
0d189a47a2 added v2 notation 2018-10-17 17:58:52 -05:00
tgruben
486cb46b49
Merge pull request #1695 from tgruben/available-shard-bug
Available shard persistance bug
2018-10-17 17:52:31 -05:00
Travis Turner
9cd0782ef1
add unprotectedSaveAvailableShards() method 2018-10-17 17:33:13 -05:00
Travis Turner
03e68aaa69 Update field_internal_test.go 2018-10-17 12:38:29 -05:00
Todd Gruben
c0a3b7a781 fmt 2018-10-17 12:35:00 -05:00
Todd Gruben
829779f550 Merge remote-tracking branch 'upstream/master' into available-shard-bug 2018-10-17 12:11:24 -05:00
Todd Gruben
30059f9e7e force truncate of available shards file to avoid corruption 2018-10-17 12:06:54 -05:00
Todd Gruben
9bb372a09e Merge branch 'fix-logger' of github.com:tgruben/pilosa into fix-logger 2018-10-17 11:12:57 -05:00
Todd Gruben
e5e2237fc0 changed order of logger options 2018-10-17 11:12:37 -05:00
tgruben
96e7107870
Merge branch 'master' into fix-logger 2018-10-17 10:52:51 -05:00
Ben Johnson
442c872b33
Merge pull request #1624 from benbjohnson/delete-available-shard
Add DeleteAvailableShard()
2018-10-17 09:47:35 -06:00
Todd Gruben
0df193cf98 revert to existing api with panic per jaffee 2018-10-17 10:29:58 -05:00
Ben Johnson
f8608227d1
Add DeleteAvailableShard()
This commit adds the ability to remove an 'available shard'
from the shard cache. This does not affect shards known to be
available because of local data.
2018-10-17 08:50:06 -06:00
Matt Jaffee
b6a953cade
cleanup groupby - more comments, remove panic, remove dup test 2018-10-16 19:56:54 -05:00
Matt Jaffee
1029a6ca83
Merge branch 'master' into new-rows-iterate 2018-10-12 19:03:00 -05:00
Matt Jaffee
38f459a6d4
add GroupBy(Rows(column)) test and fix comments 2018-10-12 18:58:27 -05:00
Matt Jaffee
fb706ab883
add GroupBy Rows(limit) test and fix bug
run all group by tests on two cluster sizes
2018-10-12 18:47:41 -05:00
Matt Jaffee
431185110b
add different shard test and simplify checking logic
we now guarantee result order
2018-10-12 15:58:28 -05:00
Matt Jaffee
a4edd39715
use intersectionCounts for final row of groupBy record
since we only need the counts and not the data, this optimization actually
provides enormous speedup (2x?) and massive decrease in allocations.

also in this commit (unfortunately), a bunch of renaming and documentation,
returning a GroupCount from the GroupBy iterator instead of a ppi (ppi is now
gone).

also added TODOs for tests and benchmarks
2018-10-12 15:30:25 -05:00
tgruben
1d102e283d
Merge branch 'master' into fix-logger 2018-10-12 02:11:44 -05:00
Matt Jaffee
07d279a155
implement mergeGroupCounts w/o map, remove dead code
move rowFilters to fragment.go

new mergeGroupCounts implementation takes limit into account while merging,
exploits inherent order of group count results.
2018-10-11 19:06:46 -05:00
Yuce Tekol
db76437d50
Merge pull request #1683 from yuce/1681-add-missing-call-tests
Adds missing rowID/Key columnID/Key tests
2018-10-12 02:51:48 +03:00
Matt Jaffee
9d896c5d2f
implement alternate groupByIterator using fragment rowIterator
doesn't re-intersect the same rows for every record
2018-10-11 18:01:44 -05:00
Yuce Tekol
d1dbee749b
Merge branch 'master' into 1681-add-missing-call-tests 2018-10-11 21:37:40 +03:00
Matt Jaffee
f9cb7f8fec
add some group by benchmarks 2018-10-11 12:08:17 -05:00
Yuce Tekol
2e2a281e30
More tests for Row call 2018-10-11 17:38:12 +03:00
Travis Turner
f62dbc00b9
Merge pull request #1686 from travisturner/holder-reopen
allow holder to close/open/close without panic on closing closed channel
2018-10-11 07:25:53 -05:00
tgruben
1895233ed8
Merge branch 'master' into fix-logger 2018-10-11 06:58:17 -05:00
Travis Turner
69ef4a3746
allow holder to close/open/close without panic on closing closed channel 2018-10-10 21:29:03 -05:00
Matt Jaffee
360623230f
get a somewhat better groupBy working that passes new tests
one test still fails due to reordering during merging
2018-10-10 21:03:45 -05:00
Yuce Tekol
616cc0f86b
More refactoring 2018-10-10 17:34:20 +03:00
Yuce Tekol
9a7dac4339
refactored call tests 2018-10-10 17:13:24 +03:00
Matt Jaffee
603b0e5369
fix logic bug applying limit to group by rows
check in failing test showing how applying the limit to each rows query can
cause the query to falsely return no results
2018-10-09 19:27:10 -05:00
Matt Jaffee
578c594755
convert GroupBy tests to use new utils; fix case where index exists 2018-10-09 19:13:12 -05:00
Matt Jaffee
45fb6f0c06
add some new test utils and test Rows calls on cluster 2018-10-09 18:44:48 -05:00
Matt Jaffee
36a539d24e
Merge branch 'master' into new-rows-iterate 2018-10-09 12:27:05 -05:00
Matt Jaffee
1474884f5d
use existing var instead of recalculating
silly mistake - thanks todd
2018-10-09 10:27:57 -05:00
Yuce Tekol
e3ccece5d2
Merge branch 'master' into 1681-add-missing-call-tests 2018-10-09 17:27:32 +03:00
Yuce Tekol
a08865a2c8
Adds missing rowID/Key columnID/Key tests 2018-10-09 17:24:33 +03:00
Matt Jaffee
e2bbcb28e5
fix linter issues 2018-10-08 19:10:16 -05:00
Matt Jaffee
cbd7e945b2
get GroupBy working with "Rows" child calls, remove fieldDirectives
had to implement decoders for RowIDs and RowIdentifiers - a sign that we need
better testing of remote Rows calls
2018-10-08 19:04:29 -05:00
Matt Jaffee
c172ca0680
combine fragment.rows and rowsForColumn with generalized filter
use filter funcs with closures for state instead of methods on structs. seems a
bit cleaner.
2018-10-08 16:16:39 -05:00
Yuce Tekol
396ec6e271
Merge pull request #1677 from yuce/1632-move-columnattrs
Fixes #1632
2018-10-05 22:53:17 +03:00
Yuce Tekol
37d1cfbbd7
Updated with master 2018-10-05 22:07:01 +03:00
Travis Turner
2d81d85c4d
Merge pull request #1679 from travisturner/range-with-keys
ensure a Range() query with field keys is handled correctly
2018-10-05 11:35:30 -05:00
Travis Turner
051b71e540
ensure a Range() query with field keys is handled correctly 2018-10-05 11:30:47 -05:00
Travis Turner
87a2bff58f
Merge pull request #1666 from travisturner/store-function
Store() function
2018-10-05 10:52:04 -05:00
Yuce Tekol
b617db84eb
gfmt'ed 2018-10-05 17:44:02 +03:00
Yuce Tekol
b6981930b1
ColumnAttrsSet omit empty ID 2018-10-05 16:47:53 +03:00
Travis Turner
16811bc04c
add a "store intersect" example to the Store() docs 2018-10-05 08:45:07 -05:00
Travis Turner
a6190f5cfa
Store() docs 2018-10-05 08:45:07 -05:00
Travis Turner
338f69b71d
replace switch with simplified if statement 2018-10-05 08:45:07 -05:00
Travis Turner
3d33cdbb74
implement Store() in the executor (i.e. setRow()) 2018-10-05 08:45:07 -05:00
Travis Turner
619bc1bcd9
implements fragment.setRow(row, rowID) 2018-10-05 08:45:05 -05:00
Yuce Tekol
bd48db1435
updated executor.Execute logic for columnAttrs with keys; added columnAttrs with keys test 2018-10-05 16:43:42 +03:00
Yuce Tekol
a028d4604a
Merge branch 'master' into 1632-move-columnattrs 2018-10-05 15:16:17 +03:00
Yuce Tekol
19177b94d1
Merge pull request #1672 from yuce/1637-trackexistence-by-default
Index trackExistence is true by default Fixes #1637
2018-10-04 22:02:25 +03:00
Yuce Tekol
b3efa25516
Merge branch 'master' into 1637-trackexistence-by-default 2018-10-04 21:47:22 +03:00
Yuce Tekol
cc17295899
Merge pull request #1676 from yuce/1667-update-populateValidators
Synced query validation for handlers
2018-10-04 21:24:04 +03:00
Yuce Tekol
f89b90306b
Merge branch 'master' into 1667-update-populateValidators 2018-10-04 20:53:43 +03:00
Yuce Tekol
ca3bf74075
Merge pull request #1670 from yuce/1660-import-roaring-valid-field-type
Fixes #1660
2018-10-03 21:41:40 +03:00
Yuce Tekol
432c2b5506
set trackExistence to true in NewIndex 2018-10-03 17:32:22 +03:00
Yuce Tekol
2d2d3e0ca4
Merge branch 'master' into 1637-trackexistence-by-default 2018-10-03 15:22:20 +03:00
Yuce Tekol
b592ee8fda
Merge branch 'master' into 1660-import-roaring-valid-field-type 2018-10-03 15:21:09 +03:00
Yuce Tekol
efed5ea3fc
Fixes #1632 2018-10-03 13:43:15 +03:00
Matt Jaffee
8cd82af2e7
remove extraneous fragment.rows* methods
variadic filters makes separate methods unnecessary
2018-10-02 09:31:13 -05:00
Matt Jaffee
4f3f2e1a49
remove noFilter and filterWithOffsetLimit
can use an empty list of filters and a list of offsetFilter followed by limit
filter respectively
2018-10-02 09:25:07 -05:00
Yuce Tekol
3539b54835
Synced query validation for handlers 2018-10-02 13:58:01 +03:00
Yuce Tekol
dc5a0da9a9
Merge pull request #1671 from yuce/add-diagnostics-arch-field
Adds diagnostics CPUArch field
2018-10-02 01:22:08 +03:00
Yuce Tekol
1ff497f7d0
Merge branch 'master' into add-diagnostics-arch-field 2018-10-02 01:09:31 +03:00
tgruben
223bbd4d85
Merge branch 'master' into fix-logger 2018-10-01 13:34:27 -05:00
Cody Soyland
4cbde825c3
Merge pull request #1673 from codysoyland/dockerhub-master-cd
Add CircleCI step to generate Docker image and push to Docker hub
2018-10-01 12:58:24 -05:00
Travis Turner
dbe4197871
ensure view closes fragment on broadcast error 2018-10-01 11:22:35 -05:00
Todd Gruben
85ebaf298d removed logging from translate store replaced with error 2018-10-01 11:04:47 -05:00
Cody Soyland
040cce162b Add CircleCI step to generate Docker image and push to Docker hub 2018-10-01 10:45:41 -05:00
Todd Gruben
a0dda250a5 converted to pilosa.logger 2018-10-01 10:11:10 -05:00
Yuce Tekol
fc6fc82f67
use FieldTypeSet 2018-10-01 17:55:56 +03:00
Yuce Tekol
f7f6ff743a
index trackExistence is true by default 2018-10-01 17:45:21 +03:00
Yuce Tekol
2830fb46e6
Adds diagnostics CPUArch field 2018-10-01 15:31:13 +03:00
Yuce Tekol
066c3a4853
Fixes #1660 2018-10-01 14:15:51 +03:00
Matt Jaffee
f94cd8ae7d
add translation code for GroupBy "previous" arg 2018-09-28 14:30:18 -05:00
Matt Jaffee
61089981a2
remove check for column in shard in executeRowsShard
the check happens in executeRows and frag.rowsForColumn will panic if given a
column id not in its shard.
2018-09-28 10:20:48 -05:00
Matt Jaffee
ed1b09a1cd
fix columnID<>shard checks in executor and fragment
fragment panics if rowsForColumn is called with a column id not in the
fragment's shard. The justification for this is that we're wasting resources if
we're sending requests for a specific column to any shard other than the one
which contains that column.
2018-09-28 10:17:53 -05:00
Matt Jaffee
93e9f242fe
test Rows call with row keys, fix column id problem 2018-09-27 17:07:15 -05:00
Matt Jaffee
7d24276a98
rename "columns" to "rows" in Rows test so it makes sense 2018-09-27 16:18:37 -05:00
Matt Jaffee
78ff75690d
convert Rows to use previous/limit
pass previous+1 directly to fragment.rows so that the iterator can seek directly
to the start point. handle limit inside reduce so it can skip out early and
avoid extra allocation.
2018-09-27 16:14:40 -05:00
Matt Jaffee
ac98fcb6d4
rename RowIDs PQL to Rows 2018-09-26 16:09:05 -05:00
Matt Jaffee
4face45c2a
rename RowIDs methods to Rows 2018-09-26 16:03:26 -05:00
Cody Soyland
1706e9b4e1
Merge pull request #1665 from codysoyland/translate-mapsize-errors
Wrap translation store errors, decrease test map size to prevent failure on 32-bit
2018-09-25 12:19:03 -05:00
Cody Soyland
81dbe38081 Change wording for consistency 2018-09-25 11:59:52 -05:00
Cody Soyland
2521922d7b Properly wrap translation store errors, decrease test map size to prevent failure on 32-bit 2018-09-25 11:35:58 -05:00
tgruben
3f73079450
Merge pull request #1664 from tgruben/n-to-int32
shrank n(container bit count cache) to int32
2018-09-25 11:12:52 -05:00
Todd Gruben
6aad568f28 added TODO(2.0) comment 2018-09-25 11:07:01 -05:00
tgruben
d3862ea1eb
Merge branch 'master' into n-to-int32 2018-09-25 10:47:49 -05:00
Todd Gruben
be3bc105cd fixed upconvert;reverted to released interface 2018-09-25 10:40:04 -05:00
Travis Turner
5054cecc5f
Merge pull request #1645 from travisturner/delete-row
implement ClearRow() query
2018-09-25 09:41:45 -05:00
Travis Turner
1a01e3d4dc
Merge branch 'master' into delete-row 2018-09-25 09:21:59 -05:00
Travis Turner
82cadf9476
Merge pull request #1663 from travisturner/save-available-shards
store remoteAvailableShards to file
2018-09-25 09:19:01 -05:00
Todd Gruben
64e86614f8 shrank n(container bit count cache) to int32 2018-09-25 09:14:19 -05:00
Travis Turner
ee503b6ec0
remove unnecessary buffer on available shard write to file 2018-09-24 16:49:39 -05:00
Travis Turner
4a411067a5
remove Set() (and Clear()) from vector interface, and add error to return 2018-09-24 16:16:22 -05:00
Travis Turner
506e6dcf51
change ClearRow validation to whitelist of field types 2018-09-24 16:03:50 -05:00
Travis Turner
1b6d738bab
Support ranked cache value=0.
Since there is no way to remove a value from the cache (because
the interface doesn't support it), this PR modifies the ranked
cache implemetation to allow setting the cache value to 0 for a
row. Doing so effectively removes that row from the cache. Values
below the threshold (other than 0) are still ignored by the
ranked cache's Add() method.
2018-09-24 15:52:44 -05:00
Travis Turner
b6e99734f0
implement ClearRow() query 2018-09-24 15:52:43 -05:00
Travis Turner
cdfcd6db5e
store remoteAvailableShards to file 2018-09-24 15:37:43 -05:00
Travis Turner
365fbdf244
Merge pull request #1662 from travisturner/slice-decode-bug
fixes pass-by-value issue in proto decode
2018-09-24 15:17:18 -05:00
Travis Turner
c9858f22e9
Merge branch 'master' into slice-decode-bug 2018-09-24 15:08:09 -05:00
tgruben
73fc1e660b
Merge pull request #1619 from tgruben/bounds-check
removing bounds check
2018-09-24 13:22:37 -05:00
Travis Turner
1039390686
fixes pass-by-value issue in proto decode 2018-09-24 13:11:54 -05:00
tgruben
e62be47667
Merge branch 'master' into bounds-check 2018-09-24 12:59:10 -05:00
Travis Turner
fcb3749bd8
Merge pull request #1658 from travisturner/bool-field-vector
add support for Bool fields
2018-09-21 11:03:58 -05:00
Travis Turner
4c1709b8bd
fix spelling mistake 2018-09-21 09:25:41 -05:00
Travis Turner
4f17dbdbf1
add support for Bool fields
prevent import of non-boolean row values to bool fields
2018-09-21 09:25:41 -05:00
Cody Soyland
6f304b1a98
Merge pull request #1653 from codysoyland/configurable-translate-map-size
Make translate map size configurable
2018-09-20 16:33:18 -05:00
Cody Soyland
e4a1281997 Merge branch 'master' into configurable-translate-map-size 2018-09-20 16:05:43 -05:00
Cody Soyland
52ba336461 Address code review feedback 2018-09-20 16:05:28 -05:00
Cody Soyland
9e14f126f0
Merge pull request #1655 from codysoyland/skip-prerelease-if-pr
Do not run prerelease in CI if this is a pull request
2018-09-20 14:20:54 -05:00
Cody Soyland
0832932cb3
Merge branch 'master' into skip-prerelease-if-pr 2018-09-20 14:15:40 -05:00
Matt Jaffee
3ca7944fe3
remove unecessary lines
confirmed that bounds checks are still avoided by
go test -gcflags="-d=ssa/check_bce/debug=1"

./roaring.go:3387:8: Found IsSliceInBounds
./roaring.go:3388:8: Found IsSliceInBounds
./roaring.go:3436:21: Found IsSliceInBounds
2018-09-20 12:37:28 -05:00
Travis Turner
d68efca238
Merge pull request #1656 from travisturner/mutex-import
ensure mutex imports unset previous columns
2018-09-20 11:38:09 -05:00
Travis Turner
995a24d0af
ensure mutex imports unset previous columns 2018-09-20 11:25:43 -05:00
tgruben
9b0cc07b30
Merge branch 'master' into bounds-check 2018-09-20 09:09:27 -05:00
Travis Turner
1a4597f67f
Merge pull request #1651 from travisturner/import-timestamp-as-utc
treat import timestamps as UTC
2018-09-19 17:09:43 -05:00
Travis Turner
b86478c613
test to ensure views match UTC time 2018-09-19 16:17:09 -05:00
Travis Turner
e7481f4fd2
treat import timestamps as UTC 2018-09-19 16:17:09 -05:00
Yuce Tekol
151fd62e64
Merge pull request #1654 from yuce/trivial-roaring-bitmap-comment
Trivial comment fix
2018-09-19 23:16:11 +03:00
Cody Soyland
42293c58a5 Do not run prerelease in CI if this is a pull request 2018-09-19 14:11:33 -05:00
Cody Soyland
ebc4d7fc13 Set low map size for 32-bit 2018-09-19 13:37:42 -05:00
Cody Soyland
2394d36108 Adjust tests, fix 32-bit config 2018-09-19 13:30:22 -05:00
Yuce Tekol
fcdc3b7427
trivial comment fix 2018-09-19 20:54:06 +03:00
Cody Soyland
7a32745b28 Make translate map size configurable. 2018-09-19 12:35:00 -05:00
Matthew Jaffee
86d238edb0
Merge pull request #4 from travisturner/new-rows-iterate-cleanup
New rows iterate cleanup
2018-09-18 14:19:05 -05:00
Travis Turner
0ab3e72520
refactor mergeGroupCounts function 2018-09-18 14:09:52 -05:00
Travis Turner
71ad297450
change Rows() to RowIDs() and add RowIdentifiers return type to hold row keys 2018-09-18 12:45:09 -05:00
Travis Turner
f0666b2be0
change GroupByCounts to []GroupCount 2018-09-18 12:39:09 -05:00
Travis Turner
b6d386ba53
fix tests 2018-09-18 12:37:35 -05:00
Travis Turner
96b4086360
plug in in translation. adjust output format. 2018-09-18 12:37:26 -05:00
Travis Turner
de071d548a
remove additional decodeFieldRow (and hopefully allocation) 2018-09-18 12:37:10 -05:00
Travis Turner
e1b938e52c
add FieldRow struct to replace the groupBy string key 2018-09-18 12:36:46 -05:00
Matt Jaffee
54ce537327
copy non roaring-import code from Todds's row-iterate PR
tests passing
2018-09-17 16:01:51 -05:00
Yuce Tekol
74780528d7
Merge pull request #1646 from yuce/roaring-fast-add
Adds DirectAdd function to roaring.Bitmap
2018-09-17 22:04:30 +03:00
Yuce Tekol
e664a0e42f
rename add -> DirectAdd 2018-09-17 20:25:14 +03:00
Yuce Tekol
37fdd73a7f
DirectAdd adds a single value 2018-09-17 17:16:03 +03:00
Yuce Tekol
09c24cd3be
Changed the signature of Bitmap.DirectAdd function 2018-09-17 17:10:02 +03:00
Yuce Tekol
266051dd26
Adds DirectAdd function to roaring.Bitmap 2018-09-17 16:25:34 +03:00
Todd Gruben
fe8756927c manual gofmt 2018-09-14 15:40:37 -05:00
Todd Gruben
51e57ad550 code cleanup 2018-09-14 14:46:02 -05:00
tgruben
eb7af13be2
Merge branch 'master' into bounds-check 2018-09-14 14:37:23 -05:00
Travis Turner
55bb12a434
Merge pull request #1643 from travisturner/generate-update
re-generate the apimethod stringer
2018-09-14 10:32:16 -05:00
Todd Gruben
136ee7beab updated comments and gofmt 2018-09-14 10:27:33 -05:00
Travis Turner
2223b23b95
re-generate the apimethod stringer 2018-09-14 09:40:48 -05:00
Travis Turner
734c31d963
Merge pull request #1622 from travisturner/roaring-import
Roaring import
2018-09-13 22:43:20 -05:00
Matt Jaffee
495af54c10
Merge branch 'master' into roaring-import 2018-09-13 15:50:16 -05:00
Matt Jaffee
870c5e131f
replace waitgroup with errgroup to avoid race on err 2018-09-13 15:27:00 -05:00
Matt Jaffee
f943c17e0b
ImportRoaring, add remote arg, fix data copy bug
also, handle err properly in client method instead of discarding.
2018-09-13 15:05:05 -05:00
Matt Jaffee
b412309447
rename standard roaring to "official" throughout 2018-09-13 13:38:18 -05:00
Matt Jaffee
b2ec5e373e
fixup explanatory comment 2018-09-13 13:33:51 -05:00
Matt Jaffee
7b0d4d75b4
remove validators on import-roaring and test handler
validators are for query args, not url vars. Also some misc cleanup and error
handling in the handler.
2018-09-13 13:14:35 -05:00
Matt Jaffee
fd655c998e
rename all instances of roaringbytes
function names now importRoaring and byte slice args are just called data. Also
renamed http endpoint from /importroaring to /import-roaring
2018-09-13 12:27:23 -05:00
Matt Jaffee
9e7cfeedc9
readability changes in fragment.go 2018-09-13 11:41:46 -05:00
Matt Jaffee
af7d405b11
add explanatory comment and move comment to correct spot 2018-09-13 10:41:36 -05:00
Matt Jaffee
f006df7758
re-order ImportRoaringBytes args to be more consistent 2018-09-13 10:39:00 -05:00
Matt Jaffee
c6817340c7
rename sliceWidth->shardWidth 2018-09-13 10:31:58 -05:00
Matt Jaffee
79c783eaf8
add nolint directive
there isn't much piont in making snapshot take a WriterTo, because the only
thing that's going to be written to a fragment is a roaring bitmap. making it
WriterTo just makes it slightly more annoying to jump into the Bitmap.WriterTo
implementation. since it's a private function, it should be straightforward to
change this in the future if the need arises.
2018-09-12 17:31:57 -05:00
Matt Jaffee
4a5f12631c
more naked returns 2018-09-12 17:29:35 -05:00
Matt Jaffee
d0d0bdd722
simplify fragment.unprotectedRow (unparam) 2018-09-12 17:25:12 -05:00
Matt Jaffee
3bc9c66f5e
remove some naked returns and simplify 2018-09-12 17:21:17 -05:00
Matt Jaffee
70e9da3b75
fmt -s fragment_internal_test 2018-09-12 17:13:07 -05:00
Matt Jaffee
f8569102f5
update some fragment comments re: the cache 2018-09-12 17:10:28 -05:00
Matt Jaffee
3ea07ae3a7
use cache.Recalculate instead of Invalidate for imports
Invalidate does not always rebuild the cache - if the last rebuild is < 10s ago,
it does nothing. We always want to rebuild the cache after imports.

Also updated the comments around recalculate/invalidate to clarify.
2018-09-12 17:07:46 -05:00
Matt Jaffee
14a8362261
roaring import - add cache invalidate and broken test 2018-09-12 16:48:07 -05:00
Matt Jaffee
b5a14de1fd
roaring import: fix api doc, refactor/rename, test merge 2018-09-12 16:11:51 -05:00
Matt Jaffee
a3243f99e1
linter fixes - reorder return vals, remove unused const 2018-09-12 13:24:59 -05:00
Todd Gruben
156260e68e roaring allowed import to merge with existing data 2018-09-12 13:20:07 -05:00
Matt Jaffee
8254d0fadd
improve import roaring docs, check errors 2018-09-12 12:08:57 -05:00
Matt Jaffee
d3717e2afe
make Bitmap.UnmarshalBinary work for roaring or pilosa format 2018-09-12 10:50:05 -05:00
Matt Jaffee
cf47950bd7
gofmt all 2018-09-12 10:06:03 -05:00
Travis Turner
6a15ceb4ed
Merge pull request #1635 from travisturner/not
implements Not() query
2018-09-12 09:21:14 -05:00
Travis Turner
424ca9378a
fixing a copy/paste issue in the Not() docs 2018-09-12 09:20:31 -05:00
Travis Turner
d78d9511ed
Merge branch 'master' into not 2018-09-12 08:49:04 -05:00
Yuce Tekol
c5e86e0395
Merge pull request #1636 from yuce/options-call-docs
Added docs for the Options call
2018-09-12 15:43:07 +03:00
Yuce Tekol
63f1b65c0a
updated Options docs 2018-09-12 00:59:44 +03:00
Yuce Tekol
b1af66a427
updated Options docs 2018-09-12 00:57:45 +03:00
Yuce Tekol
e4b5449388
Merge branch 'master' into options-call-docs 2018-09-12 00:54:21 +03:00
Yuce Tekol
ec9371aae4
Updated Options docs 2018-09-12 00:53:40 +03:00
Cody Soyland
e13434a253
Merge pull request #1634 from codysoyland/metalinter-deadline-increase
Increase gometalinter deadline so CI stops failing
2018-09-11 16:41:25 -05:00
Cody Soyland
6944be7033
Merge branch 'master' into metalinter-deadline-increase 2018-09-11 16:23:46 -05:00
Yuce Tekol
96893e2e9f
Merge branch 'master' into options-call-docs 2018-09-12 00:04:52 +03:00
Yuce Tekol
2dcdd9614c
Added docs for the Options call 2018-09-12 00:01:22 +03:00
Matthew Jaffee
c3dfb7f581
Merge pull request #1612 from jaffee/1609-log-race
remove unused log buffers from test cluster, fixes race
2018-09-11 15:42:22 -05:00
Cody Soyland
c05d751516
Merge branch 'master' into metalinter-deadline-increase 2018-09-11 15:39:42 -05:00
Travis Turner
319456bbd7
implements Not() query 2018-09-11 15:29:43 -05:00
Matt Jaffee
4ea48e1b40
remove unused log buffers from test cluster, fixes race
the buffers were unused internally and external users had no access to them.
Those wishing to read the logs of the cluster in tests may replace stdout/stderr
with buffers on the Command struct.

The race occurred when a node was stopped and then started again. some
memberlist goroutines might not be completely cleaned up by the time the node
restarted, and then two loggers were using the same output buffer.
2018-09-11 15:28:16 -05:00
Travis Turner
3315c9e35c
Merge pull request #1628 from travisturner/not-null-field
implement NotNull field with index option trackNotNull
2018-09-11 15:27:03 -05:00
Travis Turner
a89e1c521b
benchmark import instead of set on existence field 2018-09-11 15:15:37 -05:00
Travis Turner
f7abf60627
add lock around existencFld 2018-09-11 15:15:37 -05:00
Travis Turner
f8c745340f
stop tracking existence if the existence field is deleted 2018-09-11 15:15:37 -05:00
Travis Turner
9b4c67ee60
rename notnull to exists 2018-09-11 15:15:37 -05:00
Travis Turner
8b99414029
apply fieldName validation to index.CreateField 2018-09-11 15:14:58 -05:00
Travis Turner
3d7fc0c1c6
remove unnecessary timestamp slice allocation 2018-09-11 15:14:58 -05:00
Travis Turner
a433862c98
add tests for the notnull tracking 2018-09-11 15:14:57 -05:00
Travis Turner
4c67cb18ed
update notnull field on imports 2018-09-11 15:13:56 -05:00
Travis Turner
60e83fc6db
rename bitmap to row in tests 2018-09-11 15:13:56 -05:00
Travis Turner
d57dae3749
implement NotNull field with index option trackNotNull 2018-09-11 15:13:55 -05:00
Yuce Tekol
8adb936993
Merge pull request #1631 from yuce/700-query-call
Implements Query call and excludeRowAttrs, excludeColumns, columnAttrs and shards args
2018-09-11 22:53:58 +03:00
Cody Soyland
975e013deb Increase gometalinter deadline so CI stops failing 2018-09-11 14:38:04 -05:00
Yuce Tekol
408a3531ec
updated comment 2018-09-11 22:18:31 +03:00
Yuce Tekol
80c1a734ba
trivial 2018-09-11 20:51:32 +03:00
Yuce Tekol
70d386039f
trivial 2018-09-11 20:47:15 +03:00
Yuce Tekol
c2d23b1f00
Renamed Opt call to Options 2018-09-11 20:42:06 +03:00
Yuce Tekol
465028e9c3
Renamed Query to Opt; added multiple Opt test 2018-09-11 17:19:12 +03:00
Yuce Tekol
45abad5147
trivial 2018-09-11 11:50:54 +03:00
Yuce Tekol
70ceb5809b
Added columnAttrs to Query call 2018-09-11 11:42:00 +03:00
Yuce Tekol
aa618c30d5
Implements Query call excludeRowAttrs, excludeColumns and shards args 2018-09-10 17:29:55 +03:00
Yuce Tekol
0efc42f792
Merge pull request #1625 from yuce/1623-pilosa-import-field-options
Added field options to pilosa import
2018-09-07 00:32:21 +03:00
tgruben
5589324865
Merge branch 'master' into roaring-import 2018-09-06 16:28:38 -05:00
Todd Gruben
93e5767325 cleanup #1622 2018-09-06 16:27:10 -05:00
Yuce Tekol
b4a3fef3dc
Merge branch 'master' into 1623-pilosa-import-field-options 2018-09-06 23:56:30 +03:00
Yuce Tekol
1ad5bf20d2
Adds more tests; better help text; updated defaults for cache type, size 2018-09-06 23:19:10 +03:00
Travis Turner
69467f31f9
Merge pull request #1626 from travisturner/testing-TB
replace *testing.T with interface testing.TB
2018-09-06 11:31:15 -05:00
Travis Turner
a6f22eb8b3
replace *testing.T with interface testing.TB 2018-09-06 09:43:21 -05:00
Yuce Tekol
81f126dd34
Added field options to pilosa import 2018-09-06 17:04:07 +03:00
Yuce Tekol
0ac1e25a07
Merge pull request #1621 from yuce/1570-import-cmd-keys-options
Adds --field-keys and --index-keys options to pilosa import
2018-09-06 05:56:04 +03:00
Yuce Tekol
4efd11bb1f
Merge branch 'master' into 1570-import-cmd-keys-options 2018-09-05 22:59:13 +03:00
Yuce Tekol
48bd76b967
Removed --string-keys option from pilosa import 2018-09-05 22:58:23 +03:00
Yuce Tekol
748a2d01e3
Merge pull request #1620 from yuce/1538-cmd-package
Use passed stdin, stdout and stderr in the cmd package. Fixes #1538
2018-09-05 21:45:09 +03:00
Travis Turner
8a1f8659fa
change test to use exported UnmarshalStandardRoaring() 2018-09-05 10:13:15 -05:00
Todd Gruben
de478870fb
found deadlock in new code 2018-09-05 10:13:15 -05:00
Todd Gruben
1d99da1f28
added support for both pilosa and standard roaring uploads 2018-09-05 10:13:15 -05:00
Todd Gruben
cc80e0b0e4
initial support for bulk importing standard roaring files per shard 2018-09-05 10:13:15 -05:00
Todd Gruben
019ca63cf4
add support for reading standard roaring bitmaps to pilosa/roaring. 2018-09-05 10:13:15 -05:00
Yuce Tekol
fe1208ac65
Fix std{in,out,err} in export cmd 2018-09-05 17:37:44 +03:00
Yuce Tekol
7b872e00cb
Implements #1570 2018-09-05 17:10:56 +03:00
Yuce Tekol
480c853a3e
Use passed stdin, stdout and stderr in the cmd package. Fixes #1538 2018-09-05 16:23:31 +03:00
Todd Gruben
38e3ce10fe removing bounds check 2018-09-04 14:01:26 -05:00
Yuce Tekol
6c43f1aad7
Merge pull request #1614 from yuce/client-doc-update
Updated Go client sample to match latest master
2018-09-04 19:24:39 +03:00
Yuce Tekol
0b38a4d956
updated go client sample to match latest master 2018-08-29 23:13:04 +03:00
Travis Turner
10eea2db4c
Merge pull request #1600 from benbjohnson/available-shards
Maintain available shards set
2018-08-23 07:32:37 -05:00
Ben Johnson
f4c9c0fed3
Maintain available shards set.
This commit removes the previous `MaxShard` tracking and replaces
it with an `Available Shards` set tracking. This allows sparse shard
tracking without implicitly tracking all shards in between.
2018-08-22 07:57:58 -06:00
Cody Soyland
b22780ccf1
Merge pull request #1611 from codysoyland/release-v1.1.0
Release v1.1.0
2018-08-21 13:12:29 -05:00
Cody Soyland
bc890f83f3 Add link to v1.1 diff 2018-08-21 13:03:07 -05:00
Cody Soyland
944d8de154 Travis has good grammar 2018-08-21 13:01:48 -05:00
Cody Soyland
3cb8a10cbd Release v1.1.0 2018-08-21 12:19:22 -05:00
Cody Soyland
83dee41478 Update CHANGELOG with changes from v1.0 branch 2018-08-21 11:52:22 -05:00
Cody Soyland
b9f947db15
Merge pull request #1610 from codysoyland/circleci
Add CircleCI
2018-08-21 11:15:59 -05:00
Cody Soyland
9717dd2d6e Add CircleCI 2018-08-21 10:41:33 -05:00
Travis Turner
b7c9726a17
Merge pull request #1608 from travisturner/export-keys
add key translation to exports
2018-08-20 15:49:41 -05:00
Travis Turner
6b75988b71
add key translation to exports 2018-08-20 13:40:58 -05:00
Matthew Jaffee
060e5e3c18
Merge pull request #1607 from jaffee/1606-store-event-race
fix race on replicationClosing channel
2018-08-20 11:51:11 -05:00
Matt Jaffee
847132d02a
fix race on replicationClosing channel
monitorReplication is now not allowed to return until the goroutine it starts
cancels the context. Previously, it could return just before the context was
canceled which caused a race between its internal goroutine and
handlePrimaryStoreEvent which recreates a channel which that internal goroutine
was listening on.

handlePrimaryStoreEvent already correctly made sure that monitorReplication had
returned before recreating the channel, so proper handling of the sub-goroutine
of monitorReplication was all that was needed to avoid this race.
2018-08-20 11:11:19 -05:00
Matthew Jaffee
e426c4215e
Merge pull request #1586 from pilosa/1492-ae-and-resize
Fix - prevent anti-entropy and cluster resize from running simultaneously
2018-08-20 11:10:36 -05:00
Matt Jaffee
c133c53d0d
add missing word in test fail message 2018-08-20 10:39:41 -05:00
Matt Jaffee
e16c43c3bc
Merge branch 'master' into 1492-ae-and-resize 2018-08-20 09:13:35 -05:00
Travis Turner
f0baba9f23
Merge pull request #1603 from bmuller/require-valid-port
Require a valid port that isn't greater than 65,535
2018-08-17 08:27:12 -05:00
Brian Muller
6537c6c55a Require a valid port that isn't greater than 65,535 2018-08-16 21:05:41 -04:00
Travis Turner
99e62dddb4
Merge pull request #1602 from travisturner/sync-views
adds view parameter to sync logic for syncing time fields
2018-08-16 13:45:37 -05:00
Travis Turner
f1a460aca7
adds view parameter to sync logic for syncing time fields 2018-08-16 11:27:08 -05:00
Travis Turner
ac6feba982
Merge pull request #1601 from travisturner/import-key-values
Import key values
2018-08-15 16:44:38 -05:00
Travis Turner
177f25ee44
Add tests for importing value with column keys into integer fields.
Fix a bug in protofuf decoding of pilosa.Row.
2018-08-15 16:00:32 -05:00
Travis Turner
bf4e2e598b
add support for column keys when importing to int fields 2018-08-15 16:00:31 -05:00
Travis Turner
227e3bfc9f
Merge pull request #1599 from travisturner/import-key-cli
Support keys on import CLI
2018-08-15 15:59:35 -05:00
Travis Turner
f547cf48ce
change t.Fatal() to t.Fatalf() 2018-08-15 15:36:55 -05:00
Travis Turner
1deb42a24a
adjust test to allow time for translation replication 2018-08-15 15:15:51 -05:00
Travis Turner
2f892e5e80
change string-keys DEPRECATED message to REMOVED 2018-08-15 14:55:02 -05:00
Travis Turner
6a327a26fe
add deprecation warnings for --string-keys flag 2018-08-15 10:31:27 -05:00
Travis Turner
862dabe27d
address review comments 2018-08-14 14:37:51 -05:00
Travis Turner
0a6f0e92d8
add tests to cover the coordinator logic for multi-node clusters 2018-08-14 13:58:37 -05:00
Travis Turner
fd96d3a02e
This commit ensures that keyed imports are sent to the coordinator
node (as opposed to sending to shard0, which may or may not be the
coordinator). It adds a `Nodes()` method to the `InternalClient`
which is used by the importer to determine which node is the
coordinator.
2018-08-14 12:34:17 -05:00
Travis Turner
3793719485
fix conflicts 2018-08-14 09:37:25 -05:00
Travis Turner
1feebc890b
fix outdated test 2018-08-14 09:32:40 -05:00
Ben Johnson
a31a08c330
Support keys on import CLI. 2018-08-14 09:32:39 -05:00
Travis Turner
f278af6194
Merge pull request #1582 from travisturner/coordinator-as-primary
Treat coordinator as primary translate store.
2018-08-13 13:15:39 -05:00
Travis Turner
d50a0e853c
change NewTranslateStore() to take an interface for backward compatibility 2018-08-13 12:04:22 -05:00
Travis Turner
debd470211
replace api.server.holder with api.holder 2018-08-13 11:06:16 -05:00
Travis Turner
ceaf97de60
add translate tests to ensure that adding/removing replica nodes behaves as expected 2018-08-13 11:06:16 -05:00
Travis Turner
b304de6536
Treat coordinator as primary translate store.
Daisy-chain other nodes based on their position in the cluster.
Deprecate the `primary-url` configuration option.
2018-08-13 11:06:16 -05:00
Matt Jaffee
ab63c8e7b6
add forgotten server changes which support AE test 2018-08-09 16:07:05 -05:00
Matt Jaffee
b761121f47
test antiEntropy set to 0 works as expected 2018-08-09 15:54:31 -05:00
Matthew Jaffee
6070db077c
Merge pull request #1584 from jaffee/1249-node-failure
Add DEGRADED cluster state and handle gossip NodeLeave events correctly
2018-08-09 09:39:23 -05:00
Matt Jaffee
1901ffada6
make sure cluster gets into DEGRADED state when adding nodes
previously, losing a node could cause the cluster to go from NORMAL->DEGRADED,
but adding a node would not cause it to go from STARTING->DEGRADED. Cody brought
this up in code review.
2018-08-08 19:42:30 -05:00
Matt Jaffee
6e99a8757d
remove unnecessary memberlist constraint 2018-08-08 19:25:54 -05:00
Matt Jaffee
287ea370fd
add cluster tests for anti entropy abort 2018-08-08 15:11:52 -05:00
Matt Jaffee
0e467e5492
rename cluster.nodes and fix race in API 2018-08-08 15:11:39 -05:00
Matt Jaffee
16eff6de8c
prevent anti entropy and cluster resize from running simultaneously 2018-08-08 14:41:54 -05:00
Matt Jaffee
bb32706cb6
support DEGRADED in removeNode
now, nodes which have failed and been removed from the running cluster state can
still be manually removed to trigger a cluster resize event. This is important
because otherwise there is no way to cause the cluster to resize itself if a
node fails and you don't want to add a node to replace it.
2018-08-06 16:55:23 -05:00
Matt Jaffee
ba5b46898f
fix determineClusterState bug and add more test cases 2018-08-06 14:55:38 -05:00
Matt Jaffee
48af3adc21
add degraded cluster state and handle node failure
cluster is in degraded state when some number of nodes greater than 0 but less
than replicaN have failed. This is sort of a hybrid of "STARTING" and "NORMAL"
states because we can still respond to queries as in the NORMAL state, but we
need to be alert to re-add nodes to the cluster if they come back online which
required some changes to the cluster logic.

In order to make debugging easier, the test.MustRunCluster functionality now
names the nodes in the cluster explicitly as "node0", "node1", etc. "node0" is
the coordinator.

A number of TODOs are left in the test for scenarios that need to be checked.
2018-08-06 11:57:24 -05:00
Cody Soyland
205857e765
Merge pull request #1544 from codysoyland/1517-metalinter-unconvert
Fix linter issues: unconvert
2018-08-02 12:17:27 -05:00
Cody Soyland
e76c523135
Merge branch 'master' into 1517-metalinter-unconvert 2018-08-02 11:45:24 -05:00
Cody Soyland
c31b8c9b79
Merge pull request #1543 from codysoyland/1513-metalinter-megacheck
Fix linter issues: megacheck (unused/staticcheck/gosimple)
2018-08-02 11:44:46 -05:00
Cody Soyland
d344876587 Increase gometalinter deadline 2018-08-02 10:59:29 -05:00
Cody Soyland
f6855fac62 Remove unused newMockReadCloser 2018-08-02 10:59:16 -05:00
Cody Soyland
dd7b5f517b
Merge branch 'master' into 1513-metalinter-megacheck 2018-08-02 10:29:47 -05:00
Cody Soyland
1774efaf19
Merge pull request #1571 from codysoyland/skip-flawed-translator-test
Skip flawed translator test
2018-08-01 11:23:05 -05:00
Cody Soyland
495b4259fd Skip flawed translator test 2018-08-01 10:57:56 -05:00
Cody Soyland
edf6fa9c67
Merge pull request #1568 from codysoyland/translator-test-sleep
Add more time to sleep in translator tests due to CI failures
2018-07-31 21:05:49 -05:00
Cody Soyland
c44bb65163 Add more time to sleep in translator tests due to CI failures 2018-07-31 20:39:05 -05:00
Travis Turner
5802ba37b2
Merge pull request #1552 from travisturner/translate-cluster-fix
Translate cluster fix
2018-07-31 16:39:33 -05:00
Travis Turner
2dd655f0e9
move sleep to be after replica sync 2018-07-31 16:01:42 -05:00
Cody Soyland
68dc6489ce
Merge branch 'master' into translate-cluster-fix 2018-07-31 15:13:31 -05:00
Cody Soyland
672563891e
Merge pull request #1558 from codysoyland/go-master-error
Use string prefix instead of equality so json error message will pass on all Go versions
2018-07-31 15:13:15 -05:00
Cody Soyland
ba3bda6ac2 Use string prefix instead of equality so json error message will pass on all Go versions 2018-07-31 14:16:17 -05:00
Cody Soyland
39a82091f2 Add sleep in tests to ensure writes make it to translate store 2018-07-31 14:11:24 -05:00
Cody Soyland
be60a91a58 Clarify error string for cases when reading from non-primary translate store when given non-existent key 2018-07-31 12:19:09 -05:00
Cody Soyland
0816ea8ecb Add sleep to test to wait for key replication 2018-07-31 12:11:21 -05:00
Cody Soyland
e79cd4b199 Add JSON parsing to translator test to verify keys 2018-07-31 11:40:30 -05:00
Cody Soyland
2739ce436c Merge remote-tracking branch 'travisturner/translate-cluster-fix' into translate-cluster-fix 2018-07-31 08:36:31 -05:00
Travis Turner
ac8f8aa2e4
remove incorrect mock implementation from tranlate test 2018-07-30 11:45:34 -05:00
Travis Turner
3ffafaca4a
ignore remote translation 2018-07-30 11:45:34 -05:00
Cody Soyland
5410dcd6b1
Fix errant references of server.primaryTranslateStore to server.translateFile 2018-07-30 11:45:34 -05:00
Travis Turner
45d89d7136
Merge pull request #1555 from travisturner/setrowattrs-with-rowkeys
update parser to handle row keys on SetRowAttrs()
2018-07-27 11:44:54 -05:00
Travis Turner
13c201d768
remove errant spew.Dump() 2018-07-27 11:15:22 -05:00
Travis Turner
dfd529b2f5
update parser to handle row keys on SetRowAttrs() 2018-07-27 10:50:04 -05:00
Matthew Jaffee
ada9857f35
Merge pull request #1551 from jaffee/1550-topn-doc
fix topn spec and example in docs
2018-07-26 09:30:01 -05:00
Matt Jaffee
f90a6dff8b
fix topn spec and example in docs 2018-07-26 08:12:50 -05:00
Cody Soyland
ca800c683e Add test for cluster translator 2018-07-24 14:57:06 -05:00
Cody Soyland
a427836a9a Fix errant references of server.primaryTranslateStore to server.translateFile 2018-07-24 10:06:20 -05:00
Travis Turner
3b0eb3068f
Merge pull request #1547 from travisturner/index-options
fix places where empty IndexOptions were being used
2018-07-23 21:57:37 -05:00
Travis Turner
f9a265f94d
fix places where empty IndexOptions were being used 2018-07-23 17:23:54 -05:00
Cody Soyland
dc50204846 Fix linter issues: unconvert 2018-07-20 11:51:55 -05:00
Cody Soyland
990780bd93 Fix linter issues: staticcheck (covered by megacheck, along with gosimple and unused) 2018-07-20 11:19:24 -05:00
Cody Soyland
e9523063b5 Fix linter issues: unused 2018-07-20 10:33:29 -05:00
Cody Soyland
f01d850b17 Fix linter issues: gosimple 2018-07-20 09:06:43 -05:00
Cody Soyland
c7e29b48f9
Merge pull request #1540 from codysoyland/1521-metalinter-vet
Fix linter issues: vet
2018-07-19 16:01:10 -05:00
Cody Soyland
ba0384fb52 Merge branch 'master' into 1521-metalinter-vet 2018-07-19 15:41:28 -05:00
Cody Soyland
cf6921fce2
Merge pull request #1542 from codysoyland/index-options-json
Add IndexOptions to IndexInfo json response
2018-07-19 15:37:29 -05:00
Cody Soyland
83372c0509
Merge branch 'master' into index-options-json 2018-07-19 15:37:08 -05:00
Travis Turner
383b758c41
Merge pull request #1524 from travisturner/mutex-field-type
add mutex field type
2018-07-19 15:17:05 -05:00
Cody Soyland
86185a7530
Merge branch 'master' into index-options-json 2018-07-19 14:51:43 -05:00
Cody Soyland
23e2961d65 Add field labels to struct literals 2018-07-19 14:49:50 -05:00
Matthew Jaffee
17118f86c2
Merge branch 'master' into mutex-field-type 2018-07-19 14:48:36 -05:00
Matthew Jaffee
0e9f9d7c0b
Merge pull request #1541 from jaffee/translate-test-race
fix race cond in translate_test
2018-07-19 14:43:33 -05:00
Cody Soyland
29eba09e1e Add IndexOptions to IndexInfo json response 2018-07-19 14:11:14 -05:00
Travis Turner
f95d0f93fd
remove mapVector implementation of the vector interface 2018-07-19 14:02:58 -05:00
Travis Turner
a733fd7f67
fix spelling mistake 2018-07-19 14:01:30 -05:00
Travis Turner
4202e67a9d
add docs for the mutex field type 2018-07-19 14:01:30 -05:00
Travis Turner
06f5d04f1c
swap out mapVector for rowsVector in mutex fields 2018-07-19 14:01:30 -05:00
Travis Turner
a07ed360ab
add mutex field type 2018-07-19 14:01:29 -05:00
Matt Jaffee
68f341ea9f
fix race cond in translate_test
implements locked Reader method on test.TranslateFile. This race condition is
only present in tests, and is due to a replica referring directly to a primary
instead of through an http.TranslateStore as it would in production. This patch
requires the replica to obtain a lock while accessing the primary, and requires
test.Reopen to obtain a lock when swapping out the pilosa.TranslateStore.

I was able to reproduce the race by running: "go test
-run=TestTranslateFile_PrimaryTranslateStore -race -count=10", and could not
reproduce it after this patch.

Somewhat unrelated, I came across a "fatal error: fault" triggered by trying to
print an open pilosa.TranslateFile. This seems to be related to the mmapped
".data" field. I wrote the test to document the issue, but I don't think it's
easily fixable.
2018-07-19 12:06:31 -05:00
Cody Soyland
de99b5720f Fix linter issues: vet 2018-07-19 11:37:50 -05:00
Cody Soyland
9be45bcd60
Merge pull request #1539 from codysoyland/1512-metalinter-maligned
Fix linter issues: maligned
2018-07-19 11:21:38 -05:00
Cody Soyland
187ded0a52 Fix linter issues: maligned 2018-07-19 11:07:59 -05:00
Matthew Jaffee
e4eef98a77
Merge pull request #1533 from jaffee/1370-cluster-locking
1370 cluster locking
2018-07-19 10:18:11 -05:00
Matt Jaffee
30e0d42c3d
remove incorrect nodeJoin comment 2018-07-19 09:43:48 -05:00
Matt Jaffee
774e91ad30
finish commenting methods as unprotected. 2018-07-19 09:40:23 -05:00
Matt Jaffee
3b8b190849
add nolint unparam for setStateAndBroadcast 2018-07-19 09:17:36 -05:00
Matt Jaffee
d8597f320a
Merge branch 'master' into 1370-cluster-locking 2018-07-19 08:57:28 -05:00
Cody Soyland
18a19d2f2a
Merge pull request #1537 from codysoyland/1515-metalinter-nakedret
Fix linter issues: nakedret
2018-07-19 08:57:13 -05:00
Cody Soyland
0a9e6bca7a Re-add return variable names removed in 2aa4d6b1. 2018-07-19 08:09:05 -05:00
Cody Soyland
3ca51989c2 Merge branch 'master' into 1515-metalinter-nakedret 2018-07-19 07:52:58 -05:00
Cody Soyland
6bb6edf2fb
Merge pull request #1536 from codysoyland/1510-metalinter-ineffassign
Fix linter issues: ineffassign
2018-07-18 18:15:53 -05:00
Matt Jaffee
e1e4df67bc
fix race conds and add more locking/annotation 2018-07-18 16:47:24 -05:00
Cody Soyland
7bd2405765
Merge branch 'master' into 1510-metalinter-ineffassign 2018-07-18 16:28:49 -05:00
Cody Soyland
d27f8caacb
Merge pull request #1535 from codysoyland/1508-metalinter-gochecknoinits
Fix linter issues: gochecknoinits
2018-07-18 16:28:25 -05:00
Cody Soyland
2aa4d6b12f Fix linter issues: nakedret 2018-07-18 15:23:36 -05:00
Cody Soyland
d4510172d3 Fix linter issues: ineffassign 2018-07-18 14:02:56 -05:00
Cody Soyland
0b86bbb4f5 Fix linter issues: gochecknoinits 2018-07-18 11:58:27 -05:00
Cody Soyland
cceb1ebdf6
Merge pull request #1534 from codysoyland/1505-metalinter-deadcode
Fix linter issues: deadcode
2018-07-18 10:27:03 -05:00
Cody Soyland
a962a0c526 Fix linter issues: deadcode 2018-07-17 17:17:42 -05:00
Travis Turner
4490f246cc
Merge pull request #1532 from travisturner/fragment-rows
Fragment rows() and rowsForColumn()
2018-07-17 17:03:52 -05:00
Matt Jaffee
fa755fdd81
fix ClusterCluster not to broadcast to self.
stops deadlock when cluster has appropriate internal locking
2018-07-17 16:34:49 -05:00
Matt Jaffee
7efdacd028
rename setState to unprotected 2018-07-17 16:34:48 -05:00
Matt Jaffee
18321b88f9
rename setID as unprotected and add some "unprotected" comments 2018-07-17 16:34:48 -05:00
Matt Jaffee
04bdc67d7f
rename a few things to unprotected* and use safe coordinatorNode in setNodeState 2018-07-17 16:34:48 -05:00
Matt Jaffee
8b2d8295d1
rename cluster.coordinatorNode to unprotectedCoordinatorNode 2018-07-17 16:34:48 -05:00
Travis Turner
dc5d7a66ef
ensure that changing ShardWidth is supported in rowsForColumn() 2018-07-17 16:21:35 -05:00
Travis Turner
07abb505cc
add more testing to row iteration 2018-07-17 15:11:45 -05:00
Travis Turner
a26ebe3e23
frag.rows() and frag.rowsForColumn() from #1496 2018-07-17 15:11:45 -05:00
Cody Soyland
4aa57f56a4
Merge pull request #1530 from codysoyland/1511-metalinter-interfacer
Fix linter issues: interfacer
2018-07-17 14:15:18 -05:00
Cody Soyland
486edbec43 Merge branch 'master' into 1511-metalinter-interfacer 2018-07-17 13:41:11 -05:00
Cody Soyland
3017740f3a
Merge pull request #1529 from codysoyland/1514-metalinter-misspell
Fix linter issues: misspell
2018-07-17 13:38:43 -05:00
Cody Soyland
8efbb02fb1 Merge branch 'master' into 1514-metalinter-misspell 2018-07-17 12:38:12 -05:00
Cody Soyland
97b0bcfcc2
Merge pull request #1528 from codysoyland/1515-metalinter-unparam
Fix linter issues: unparam
2018-07-17 12:37:03 -05:00
Cody Soyland
573ec91fc2 Fix linter issues: interfacer 2018-07-17 12:36:02 -05:00
Cody Soyland
2635759893 Fix linter issues: misspell 2018-07-17 12:22:41 -05:00
Cody Soyland
f9625ef4fa Fix linter issues: unparam 2018-07-17 12:05:07 -05:00
Cody Soyland
379e5daf44
Merge pull request #1526 from codysoyland/1525-metalinter-goimports
Fix linter issue: goimports
2018-07-17 08:03:27 -05:00
Cody Soyland
8917359960 Merge branch 'master' into 1525-metalinter-goimports 2018-07-17 07:54:48 -05:00
Cody Soyland
b67bd2bf3f
Merge pull request #1527 from codysoyland/1509-metalinter-gofmt
Fix linter issues: gofmt
2018-07-17 07:51:51 -05:00
Cody Soyland
c464e0fe64 Fix linter issues: gofmt 2018-07-16 16:45:42 -05:00
Cody Soyland
34e3d21b34 Fix linter issue: goimports 2018-07-16 16:31:46 -05:00
Cody Soyland
7e3ae59ec3
Merge pull request #1504 from codysoyland/ci-staging
Add TravisCI staged builds
2018-07-16 14:54:29 -05:00
Cody Soyland
471cf38a56 Add TravisCI staged builds
Creates the following 3 stages:
1. add cached vendor directory, run metalinter
2. tests with env matrix
3. prerelease compilation/upload
2018-07-16 08:09:39 -05:00
Cody Soyland
fa6e0da1bb
Merge pull request #1503 from codysoyland/docs-fix
Remove errant char at top of query language doc
2018-07-13 09:39:49 -05:00
Matthew Jaffee
88f405a916
Merge branch 'master' into docs-fix 2018-07-13 09:28:22 -05:00
Cody Soyland
927a7f0cd9 Remove errant char at top of query language doc 2018-07-13 09:09:16 -05:00
Cody Soyland
cdf5649ead
Merge pull request #1502 from codysoyland/export-row-intersect
Re-export Row.Intersect
2018-07-13 08:56:49 -05:00
Cody Soyland
d22e015423 Re-export Row.Intersect
This method was previously unexported with an automatic unexporting tool. It
seems to be something that should be exported.
2018-07-13 08:03:54 -05:00
Travis Turner
e707e9c6b8
Merge pull request #1495 from travisturner/docs-fixes
another pass through the docs adjusting for fields and field types
2018-07-12 18:47:31 -05:00
Travis Turner
e5fbadba01
another pass through the docs adjusting for fields and field types 2018-07-11 17:28:48 -05:00
Cody Soyland
f50685d94c
Merge pull request #1487 from benbjohnson/proto-keys
encoding/proto: Fix key fields in protobuf.
2018-07-11 14:19:03 -05:00
Cody Soyland
1fd28560e7
Merge branch 'master' into proto-keys 2018-07-11 12:56:39 -05:00
Cody Soyland
a02a894781
Merge pull request #1493 from codysoyland/docs-console
Rename WebUI to Console, update installation instructions.
2018-07-11 12:53:41 -05:00
Cody Soyland
42c935395b Update alt text 2018-07-11 12:37:44 -05:00
Cody Soyland
3cd3cc050b
Merge branch 'master' into docs-console 2018-07-11 12:25:03 -05:00
Cody Soyland
c456662ce9
Merge pull request #1491 from codysoyland/1490-dep-ensure-vendor-only
Use `dep ensure -vendor-only` for build repeatability
2018-07-11 12:24:47 -05:00
Cody Soyland
8196fae7bc Rename WebUI to Console, update installation instructions. 2018-07-11 12:15:15 -05:00
Travis Turner
bfb21068fd
Merge pull request #1485 from travisturner/time-range
make sure time range views are calculated correctly across months
2018-07-11 12:09:32 -05:00
Travis Turner
493e77ae41
Merge branch 'master' into time-range 2018-07-11 11:50:43 -05:00
Cody Soyland
96cabf1a0a Use dep ensure -vendor-only for build repeatability. Fixes #1490. 2018-07-11 11:38:57 -05:00
Matthew Jaffee
d75f11a48d
Merge branch 'master' into proto-keys 2018-07-11 09:23:52 -05:00
Ben Johnson
8a0e99562a
encoding/proto: Fix key fields in protobuf. 2018-07-10 23:41:09 +01:00
Matthew Jaffee
302166dac6
Merge pull request #1486 from jaffee/handler-close-timeout
add a configurable timeout to http handler closing
2018-07-10 16:52:40 -05:00
Matt Jaffee
64c3dae4d7
fix error message handler->holder 2018-07-10 16:40:45 -05:00
Matt Jaffee
c2c1910671
fix comment typos 2018-07-10 16:38:55 -05:00
Matt Jaffee
b7e5f8842e
add a configurable timeout to http handler closing
refactor handler Close func to use errgroup to be a bit less messy.

refactor pilosa.Server closing to actually return an underlying error if one occurs

add option to pilosa/test.Cluster and pilosa/server.Command to control close
timeout. currently is only used by the http handler, but conceivably could be
passed as a parameter to other subsystems of pilosa/server.Command
2018-07-10 15:16:35 -05:00
Travis Turner
08fe3db1cc
Merge pull request #1483 from travisturner/close-gossip
add gossip Closer
2018-07-10 13:41:11 -05:00
Travis Turner
ce91fae141
Merge branch 'master' into close-gossip 2018-07-10 13:32:37 -05:00
Travis Turner
d24fb4e719
fix typo 2018-07-10 13:32:04 -05:00
Travis Turner
38eec5793f
make sure time range views are calculated correctly across months 2018-07-10 13:26:18 -05:00
Cody Soyland
2d903e329f
Merge pull request #1484 from codysoyland/fix-default-map-size-var
Unexport DefaultMapSize on 32-bit
2018-07-10 12:55:14 -05:00
Cody Soyland
62e172dbac Unexport DefaultMapSize on 32-bit 2018-07-10 12:15:11 -05:00
Travis Turner
4013cccb30
fix comment 2018-07-10 11:48:45 -05:00
Travis Turner
1723616aac
add gossip Closer 2018-07-10 11:41:54 -05:00
Cody Soyland
4689ada100
Merge pull request #1477 from codysoyland/update-deps-v1.0.0
Update dependencies for v1.0.0
2018-07-10 08:50:34 -05:00
Cody Soyland
1159a3a45a
Merge branch 'master' into update-deps-v1.0.0 2018-07-10 08:37:33 -05:00
Matthew Jaffee
22280762c0
Merge pull request #1478 from benbjohnson/pql-keys
peg: Allow single quoted key 'col'
2018-07-10 08:15:51 -05:00
Matthew Jaffee
cc5e4393e9
Merge branch 'master' into pql-keys 2018-07-10 07:29:42 -05:00
Travis Turner
19b2bb3fe6
Merge pull request #1480 from travisturner/rename-memberset
rename gossip.NewGossipMemberSet to gossip.NewMemberSet
2018-07-09 17:19:31 -05:00
Travis Turner
d22507d36d
rename gossip.NewGossipMemberSet to gossip.NewMemberSet 2018-07-09 17:05:58 -05:00
Cody Soyland
7728bdae71 Regenerate proto files 2018-07-09 12:53:33 -05:00
Cody Soyland
df639f101e Remove Go 1.9 support 2018-07-09 12:53:09 -05:00
Ben Johnson
bcd15ef271
peg: Allow single quoted key 'col'. 2018-07-09 18:31:27 +01:00
Cody Soyland
1c2670184d Update dependencies for v1.0.0 2018-07-09 12:11:11 -05:00
Cody Soyland
eb39dcdb06
Merge pull request #1476 from codysoyland/release-v1.0.0
Update docs and Dockerfile for 1.0.0 release
2018-07-09 12:02:03 -05:00
Cody Soyland
31970bb3c2 Update docs and Dockerfile for 1.0.0 release 2018-07-09 11:50:33 -05:00
Cody Soyland
5ec47bc795
Merge pull request #1475 from codysoyland/release-v1.0.0
Update changelog for v1.0.0
2018-07-09 11:39:30 -05:00
Cody Soyland
073a47baa5 Update changelog for v1.0.0 2018-07-09 11:34:23 -05:00
Travis Turner
7538562713
Merge pull request #1474 from pilosa/develop
Merging bug fix from develop to master
2018-07-09 11:01:36 -05:00
Cody Soyland
9e5c83ed4c
Merge branch 'master' into develop 2018-07-09 09:22:22 -05:00
Cody Soyland
7d0442a542
Merge pull request #1471 from codysoyland/release-1.0.0
Add more changelog updates
2018-07-09 09:22:06 -05:00
Cody Soyland
498447a20a
Merge branch 'master' into develop 2018-07-09 09:19:47 -05:00
Travis Turner
1f0913ff45
Merge pull request #1473 from travisturner/fix-test
Fix test
2018-07-06 20:41:02 -05:00
Travis Turner
e2406a4b52
fix typo 2018-07-06 17:50:23 -05:00
Travis Turner
babdb5ff4e
adjust test to account for new source of error downstream 2018-07-06 17:38:06 -05:00
Travis Turner
4f86b2be83
fix test that differed based on map key order 2018-07-06 17:32:04 -05:00
Cody Soyland
35884c6cf1
Merge branch 'master' into release-1.0.0 2018-07-06 17:01:35 -05:00
Cody Soyland
7c4b06fd6c
Merge pull request #1472 from codysoyland/merge-develop-master-1.0.0
Merge develop into master for 1.0.0
2018-07-06 17:00:40 -05:00
Cody Soyland
aac4118df8 Remove unnotable line from changelog 2018-07-06 08:16:56 -05:00
Cody Soyland
1c7f77d002 Merge branch 'develop' 2018-07-06 07:52:29 -05:00
Cody Soyland
6e66bbc070 Add more changelog updates 2018-07-06 07:41:58 -05:00
Matthew Jaffee
2562292074
Merge pull request #1464 from codysoyland/changelog-1.0.0
Add changelog for v1.0.0
2018-07-05 23:32:08 -05:00
Cody Soyland
de8b6ffbb2
Merge branch 'develop' into changelog-1.0.0 2018-07-05 23:19:14 -05:00
Cody Soyland
48aefd82be
Merge pull request #1470 from codysoyland/unexport-all
Unexport all possible items
2018-07-05 23:18:19 -05:00
Cody Soyland
83c55a9b0d Changelog tweaks 2018-07-05 23:16:06 -05:00
Cody Soyland
50d57ec229 Unexport server.DefaultDiagnosticsInterval (in release tag) 2018-07-05 23:11:57 -05:00
Cody Soyland
c004ffba3e Unexport test.NewIndex 2018-07-05 23:11:56 -05:00
Cody Soyland
17d212444c Unexport test.NewField 2018-07-05 23:11:56 -05:00
Cody Soyland
8e026493a4 Unexport test.NewCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
66771b6ccd Unexport test.MustOpenField 2018-07-05 23:11:56 -05:00
Cody Soyland
48730e722f Unexport test.Field.Reopen 2018-07-05 23:11:56 -05:00
Cody Soyland
9ddb881bed Unexport test.Field.Close 2018-07-05 23:11:56 -05:00
Cody Soyland
39504f8ded Unexport test.Command.Stderr 2018-07-05 23:11:56 -05:00
Cody Soyland
44e0659934 Unexport test.Command.Stdout 2018-07-05 23:11:56 -05:00
Cody Soyland
3aa759bff7 Unexport test.Command.Stdin 2018-07-05 23:11:56 -05:00
Cody Soyland
66df2cf126 Unexport test.BufferLogger 2018-07-05 23:11:56 -05:00
Cody Soyland
9236df38e9 Unexport statsd.StatsClient 2018-07-05 23:11:56 -05:00
Cody Soyland
8aa24e2c38 Unexport statsd.Prefix 2018-07-05 23:11:56 -05:00
Cody Soyland
989cc55ece Unexport statsd.BufferLen 2018-07-05 23:11:56 -05:00
Cody Soyland
167e41787f Unexport server.NewStatsClient 2018-07-05 23:11:56 -05:00
Cody Soyland
94e633b7eb Unexport server.DefaultDiagnosticsInterval 2018-07-05 23:11:56 -05:00
Cody Soyland
6023474ed4 Unexport server.Command.SetupNetworking 2018-07-05 23:11:56 -05:00
Cody Soyland
31cab33fbe Unexport roaring.SliceIterator 2018-07-05 23:11:56 -05:00
Cody Soyland
c134535229 Unexport roaring.SliceContainers 2018-07-05 23:11:56 -05:00
Cody Soyland
89c28043dd Unexport roaring.RunMaxSize 2018-07-05 23:11:56 -05:00
Cody Soyland
5ec9d3af22 Unexport roaring.NewSliceContainers 2018-07-05 23:11:56 -05:00
Cody Soyland
67cfe4dcee Unexport roaring.ContainerRun 2018-07-05 23:11:56 -05:00
Cody Soyland
bdd4fb51ef Unexport roaring.ContainerInfo 2018-07-05 23:11:56 -05:00
Cody Soyland
692b72be18 Unexport roaring.ContainerBitmap 2018-07-05 23:11:56 -05:00
Cody Soyland
9098b0d131 Unexport roaring.ContainerArray 2018-07-05 23:11:56 -05:00
Cody Soyland
72fcb37f80 Unexport roaring.Container.Optimize 2018-07-05 23:11:56 -05:00
Cody Soyland
c73fc795da Unexport roaring.BitmapInfo 2018-07-05 23:11:56 -05:00
Cody Soyland
fb7de28557 Unexport pql.TimeFormat 2018-07-05 23:11:56 -05:00
Cody Soyland
75ea43c9da Unexport pql.Parser 2018-07-05 23:11:56 -05:00
Cody Soyland
aa7f6fca75 Unexport pql.FormatValue 2018-07-05 23:11:56 -05:00
Cody Soyland
3a47638580 Unexport pql.Call.Keys 2018-07-05 23:11:56 -05:00
Cody Soyland
d6f0789511 Unexport lru.Cache.MaxEntries 2018-07-05 23:11:56 -05:00
Cody Soyland
91ce0d6c57 Unexport lru.Cache.RemoveOldest 2018-07-05 23:11:56 -05:00
Cody Soyland
ffae51549b Unexport lru.Cache.Remove 2018-07-05 23:11:56 -05:00
Cody Soyland
a22d83b880 Unexport lru.Cache.Clear 2018-07-05 23:11:56 -05:00
Cody Soyland
536f6cff8a Unexport inmem.TranslateStore 2018-07-05 23:11:56 -05:00
Cody Soyland
55d13d869f Unexport http.TranslateStore 2018-07-05 23:11:56 -05:00
Cody Soyland
04417d870d Unexport http.QueryResultTypeValCount 2018-07-05 23:11:56 -05:00
Cody Soyland
9a708234c8 Unexport http.QueryResultTypeNil 2018-07-05 23:11:56 -05:00
Cody Soyland
88b45edd7c Unexport http.QueryResultTypeBool 2018-07-05 23:11:56 -05:00
Cody Soyland
ab26a1be4b Unexport http.NewRouter 2018-07-05 23:11:56 -05:00
Cody Soyland
e460a58bfa Unexport http.InternalClient.HTTPClient 2018-07-05 23:11:56 -05:00
Cody Soyland
a3bd753cfa Unexport http.HandlerOption 2018-07-05 23:11:56 -05:00
Cody Soyland
46e40f71e4 Unexport http.Handler.AllowedOrigins 2018-07-05 23:11:56 -05:00
Cody Soyland
0a2b482945 Unexport http.Handler.Logger 2018-07-05 23:11:56 -05:00
Cody Soyland
47c402c123 Unexport http.Error.Code 2018-07-05 23:11:56 -05:00
Cody Soyland
d95aeae175 Unexport gossip.Transport.Net 2018-07-05 23:11:56 -05:00
Cody Soyland
d512b187b1 Unexport gossip.GossipMemberSetOption 2018-07-05 23:11:56 -05:00
Cody Soyland
6bc7470b0c Unexport gossip.GossipMemberSet 2018-07-05 23:11:56 -05:00
Cody Soyland
6c53ecc333 Unexport gopsutil.SystemInfo 2018-07-05 23:11:56 -05:00
Cody Soyland
7db07ea72e Unexport gcnotify.ActiveGCNotifier 2018-07-05 23:11:56 -05:00
Cody Soyland
6fbd373256 Unexport b.TreeNew 2018-07-05 23:11:56 -05:00
Cody Soyland
9a1f348580 Unexport b.Tree 2018-07-05 23:11:56 -05:00
Cody Soyland
fede4ac9f0 Unexport b.NewBTreeContainers 2018-07-05 23:11:56 -05:00
Cody Soyland
eac1bec54b Unexport b.Enumerator 2018-07-05 23:11:56 -05:00
Cody Soyland
446bfff91a Unexport b.BTreeContainers 2018-07-05 23:11:56 -05:00
Cody Soyland
c9497ec612 Unexport proto.EncodeValCount 2018-07-05 23:11:56 -05:00
Cody Soyland
b1d968f95e Unexport proto.EncodeRow 2018-07-05 23:11:56 -05:00
Cody Soyland
bafc170420 Unexport proto.EncodePairs 2018-07-05 23:11:56 -05:00
Cody Soyland
052355014d Unexport proto.EncodeNodes 2018-07-05 23:11:56 -05:00
Cody Soyland
17a0bb62b7 Unexport proto.EncodeColumnAttrSets 2018-07-05 23:11:56 -05:00
Cody Soyland
dc97e34fb7 Unexport proto.EncodeColumnAttrSet 2018-07-05 23:11:56 -05:00
Cody Soyland
eea29f664f Unexport ctl.ImportCommand.Client 2018-07-05 23:11:56 -05:00
Cody Soyland
f9a792ea49 Unexport ctl.ImportCommand.IndexOptions 2018-07-05 23:11:56 -05:00
Cody Soyland
7185c0f791 Unexport ctl.CommandClient 2018-07-05 23:11:56 -05:00
Cody Soyland
73a7588e1b Unexport cmd.NewServeCmd 2018-07-05 23:11:56 -05:00
Cody Soyland
18fd2e14c5 Unexport cmd.NewInspectCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
c86758e998 Unexport cmd.NewImportCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
4ec7a05524 Unexport cmd.NewGenerateConfigCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
da4e3b0e14 Unexport cmd.NewExportCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
b42c24eace Unexport cmd.NewConfigCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
004f1c7df1 Unexport cmd.NewCheckCommand 2018-07-05 23:11:56 -05:00
Cody Soyland
1d941efbb2 Unexport cmd.Inspector 2018-07-05 23:11:56 -05:00
Cody Soyland
35ae352599 Unexport cmd.GenerateConf 2018-07-05 23:11:56 -05:00
Cody Soyland
618f6c8af4 Unexport cmd.Conf 2018-07-05 23:11:56 -05:00
Cody Soyland
4c3600f1c4 Unexport cmd.Checker 2018-07-05 23:11:56 -05:00
Cody Soyland
9db2109278 Unexport boltdb.NewAttrCache 2018-07-05 23:11:56 -05:00
Cody Soyland
fcf6517c7e Unexport boltdb.AttrStore 2018-07-05 23:11:56 -05:00
Cody Soyland
43cac45d40 Unexport boltdb.AttrCache 2018-07-05 23:11:56 -05:00
Cody Soyland
817ede49e6 Unexport boltdb.AttrBlockSize 2018-07-05 23:11:56 -05:00
Cody Soyland
d88f275523 Unexport VerboseLogger 2018-07-05 23:11:56 -05:00
Cody Soyland
ffde862679 Unexport ValCount.Smaller 2018-07-05 23:11:56 -05:00
Cody Soyland
d7cebfa7c4 Unexport ValCount.Larger 2018-07-05 23:11:56 -05:00
Cody Soyland
cd3eac00d2 Unexport ValCount.Add 2018-07-05 23:11:56 -05:00
Cody Soyland
7807b92b13 Unexport URI.SetScheme 2018-07-05 23:11:56 -05:00
Cody Soyland
ac83bf4422 Unexport URI.SetHost 2018-07-05 23:11:56 -05:00
Cody Soyland
6f256e0edb Unexport URI.Normalize 2018-07-05 23:11:56 -05:00
Cody Soyland
a7c1795cf7 Unexport TranslateFileReader 2018-07-05 23:11:56 -05:00
Cody Soyland
e4847c498a Unexport TranslateFile.ReplicationRetryInterval 2018-07-05 23:11:56 -05:00
Cody Soyland
7a1d2c6980 Unexport TranslateFile.MapSize 2018-07-05 23:11:56 -05:00
Cody Soyland
4c2ba7b7d3 Unexport TranslateFile.Size 2018-07-05 23:11:56 -05:00
Cody Soyland
ed0372b1d0 Unexport TranslateFile.IsReadOnly 2018-07-05 23:11:56 -05:00
Cody Soyland
1af66417e1 Unexport Topology.ClusterID 2018-07-05 23:11:56 -05:00
Cody Soyland
9c160ee65e Unexport Topology.NodeIDs 2018-07-05 23:11:56 -05:00
Cody Soyland
e52f713406 Unexport Topology.RemoveID 2018-07-05 23:11:56 -05:00
Cody Soyland
65472609a5 Unexport Topology.Encode 2018-07-05 23:11:56 -05:00
Cody Soyland
3f7f82bf05 Unexport Topology.AddID 2018-07-05 23:11:56 -05:00
Cody Soyland
5709d329d5 Unexport StandardLogger 2018-07-05 23:11:56 -05:00
Cody Soyland
45f3439a7f Unexport RowSegment 2018-07-05 23:11:56 -05:00
Cody Soyland
259f5ac3b9 Unexport Row.InvalidateCount 2018-07-05 23:11:56 -05:00
Cody Soyland
018905fcd9 Unexport Row.IntersectionCount 2018-07-05 23:11:56 -05:00
Cody Soyland
3025586378 Unexport Row.Intersect 2018-07-05 23:11:56 -05:00
Cody Soyland
edf87473ee Unexport Row.ClearBit 2018-07-05 23:11:56 -05:00
Cody Soyland
6b5595d48c Unexport NopSystemInfo 2018-07-05 23:11:56 -05:00
Cody Soyland
ae5f9210d5 Unexport NopInternalQueryClient 2018-07-05 23:11:56 -05:00
Cody Soyland
e50ec6dc9d Unexport NopInternalClient 2018-07-05 23:11:56 -05:00
Cody Soyland
3e91a0d32c Unexport NodeStateReady 2018-07-05 23:11:56 -05:00
Cody Soyland
9222ef0df7 Unexport NodeIDs 2018-07-05 23:11:56 -05:00
Cody Soyland
9d882469da Unexport NewTranslateFileReader 2018-07-05 23:11:56 -05:00
Cody Soyland
2031345c86 Unexport NewTopology 2018-07-05 23:11:56 -05:00
Cody Soyland
4aa8a41fa0 Unexport NewNotFoundError 2018-07-05 23:11:56 -05:00
Cody Soyland
92d521912e Unexport NewNopSystemInfo 2018-07-05 23:11:56 -05:00
Cody Soyland
631ee915df Unexport NewNopInternalQueryClient 2018-07-05 23:11:56 -05:00
Cody Soyland
0907ee5854 Unexport NewNopInternalClient 2018-07-05 23:11:56 -05:00
Cody Soyland
5f74927d03 Unexport NewDiagnosticsCollector 2018-07-05 23:11:56 -05:00
Cody Soyland
59bbbfc1fb Unexport NewConflictError 2018-07-05 23:11:56 -05:00
Cody Soyland
a1fc587577 Unexport NewApiMethodNotAllowedError 2018-07-05 23:11:56 -05:00
Cody Soyland
b4b0fd2e64 Unexport LogEntry.HeaderSize 2018-07-05 23:11:56 -05:00
Cody Soyland
51619e81a6 Unexport IndexInfo.Options 2018-07-05 23:11:56 -05:00
Cody Soyland
13a6542a15 Unexport Index.RecalculateCaches 2018-07-05 23:11:56 -05:00
Cody Soyland
1b6846d6e6 Unexport Index.FieldPath 2018-07-05 23:11:56 -05:00
Cody Soyland
0648d0fc75 Unexport Holder.RecalculateCaches 2018-07-05 23:11:56 -05:00
Cody Soyland
3ff6851881 Unexport FieldOptions.Encode 2018-07-05 23:11:56 -05:00
Cody Soyland
5d7cb33322 Unexport Field.Logger 2018-07-05 23:11:56 -05:00
Cody Soyland
3faa51544a Unexport Field.SetTimeQuantum 2018-07-05 23:11:56 -05:00
Cody Soyland
fc49d67c0b Unexport Field.RecalculateCaches 2018-07-05 23:11:56 -05:00
Cody Soyland
55c0dcee23 Unexport Field.RangeBetween 2018-07-05 23:11:56 -05:00
Cody Soyland
cbf821123e Unexport Field.MaxShard 2018-07-05 23:11:56 -05:00
Cody Soyland
16461345f6 Unexport Field.Keys 2018-07-05 23:11:56 -05:00
Cody Soyland
ba9c5193b5 Unexport Field.ImportValue 2018-07-05 23:11:56 -05:00
Cody Soyland
a8c9c30eef Unexport ExpvarStatsClient 2018-07-05 23:11:56 -05:00
Cody Soyland
7245a93676 Unexport DiagnosticsCollector 2018-07-05 23:11:56 -05:00
Cody Soyland
761f6878fb Unexport DefaultURI 2018-07-05 23:11:56 -05:00
Cody Soyland
c102143b50 Unexport DefaultPartitionN 2018-07-05 23:11:56 -05:00
Cody Soyland
9fd8cdb007 Unexport DefaultMapSize 2018-07-05 23:11:56 -05:00
Cody Soyland
7559382115 Unexport AttrBlocks 2018-07-05 23:11:56 -05:00
Cody Soyland
71000ee6d0 Unexport ApiMethodNotAllowedError 2018-07-05 23:11:56 -05:00
Cody Soyland
b4011778dd Unexport APIOption, b.BTCIterator, API.Holder, API.Serializer, APIOption, http.Handler.API 2018-07-05 23:11:56 -05:00
Matthew Jaffee
aa1e4df101
Merge pull request #1469 from jaffee/remove-api-holder
remove Holder from API
2018-07-05 22:52:54 -05:00
Matthew Jaffee
a85124f82e
Merge branch 'develop' into remove-api-holder 2018-07-05 22:37:47 -05:00
Travis Turner
6f10bca761
Merge pull request #1461 from pilosa/docs-updates-1.0
WIP Docs updates 1.0
2018-07-05 22:22:44 -05:00
Travis Turner
cda0edd484
Merge branch 'develop' into docs-updates-1.0 2018-07-05 21:53:37 -05:00
Travis Turner
755de579d7
Merge branch 'docs-updates-1.0' of https://github.com/pilosa/pilosa into docs-updates-1.0 2018-07-05 21:52:30 -05:00
Travis Turner
6c3d8da35b
update the tutorials for 1.0 2018-07-05 21:52:07 -05:00
Matthew Jaffee
0af3cfede1
Merge pull request #1468 from travisturner/remove-dead-code
remove index and field MarshalJSON
2018-07-05 21:41:16 -05:00
Matthew Jaffee
4bf3e49343
Merge branch 'develop' into remove-dead-code 2018-07-05 21:03:22 -05:00
Matt Jaffee
15db8b4ef5
Merge branch 'develop' into remove-api-holder 2018-07-05 21:02:35 -05:00
Matthew Jaffee
e7e0a0bd4d
Merge pull request #1465 from jaffee/1126-internal-server-err
handle errors a bit better in handlePostQuery
2018-07-05 21:02:10 -05:00
Matt Jaffee
21bfa5df77
remove Holder from API 2018-07-05 20:58:25 -05:00
Cody Soyland
5a39008856
Merge branch 'develop' into 1126-internal-server-err 2018-07-05 20:50:24 -05:00
Travis Turner
bf2b4e9284
remove index and field MarshalJSON 2018-07-05 20:50:00 -05:00
Travis Turner
7bde403faa
Merge pull request #1466 from travisturner/fix-schema-output-again
ensure /schema excludes views and includes all field options (like "keys")
2018-07-05 20:44:18 -05:00
Travis Turner
c10cdc9d22
exclude views from http schema output 2018-07-05 19:15:34 -05:00
Travis Turner
9305712237
add options.keys and lowercase names to json output 2018-07-05 18:54:53 -05:00
Matt Jaffee
7873126720
handle errors a bit better in handlePostQuery 2018-07-05 18:39:25 -05:00
Alan Bernstein
1f65dbcdf2 More terminology updates 2018-07-05 18:12:30 -05:00
Matthew Jaffee
785bcde7d0
Merge pull request #1462 from codysoyland/dead-code-removal
Remove some dead code
2018-07-05 18:10:20 -05:00
Matt Jaffee
d032c8941f
Merge branch 'develop' into dead-code-removal 2018-07-05 18:02:39 -05:00
Matt Jaffee
21cf6b6e57
remove URI getters since the fields were exported for serialization 2018-07-05 17:59:18 -05:00
Matthew Jaffee
b7b46f1d66
Merge pull request #1454 from jaffee/core-structs
invert encoding/decoding and remove internal references
2018-07-05 17:51:52 -05:00
Matt Jaffee
e33682cfd2
address feedback 2018-07-05 17:38:49 -05:00
Matt Jaffee
27c071ac85
Merge branch 'develop' into core-structs 2018-07-05 17:20:30 -05:00
Cody Soyland
14c6959a38 Add changelog for v1.0.0 2018-07-05 17:03:45 -05:00
Travis Turner
6bb8d0bcc8
Merge pull request #1463 from travisturner/remove-setvalue
use Set() instead of SetValue() for integer fields
2018-07-05 17:03:00 -05:00
Cody Soyland
a0e23fa6be
Merge branch 'develop' into dead-code-removal 2018-07-05 16:59:31 -05:00
Matt Jaffee
d0485a3a19
remove unused code in row.go 2018-07-05 16:51:23 -05:00
Matt Jaffee
0a94d2f10d
Merge branch 'develop' into core-structs 2018-07-05 16:38:14 -05:00
Travis Turner
e1e9d64e86
Merge branch 'develop' into remove-setvalue 2018-07-05 16:37:55 -05:00
Travis Turner
5717e32310
fix comment for IntArg 2018-07-05 16:36:37 -05:00
Travis Turner
462b27d9a9
change executeSetBit to executeSet 2018-07-05 16:31:06 -05:00
Matthew Jaffee
c24e8d6743
Merge pull request #1451 from jaffee/remove-setupserver-calls
remove redundant calls to SetupServer
2018-07-05 16:26:49 -05:00
Matt Jaffee
def3be0f17
remove more dead code 2018-07-05 16:25:04 -05:00
Travis Turner
b7a583d6a8
use Set() instead of SetValue() for integer fields 2018-07-05 16:24:40 -05:00
Matt Jaffee
a164233c92
fix handler tests not to use internal and fix bug 2018-07-05 16:21:27 -05:00
Matt Jaffee
db2a53223d
remove internal references from api and http/* 2018-07-05 16:02:18 -05:00
Cody Soyland
2b7d937df2
Merge branch 'develop' into remove-setupserver-calls 2018-07-05 15:36:38 -05:00
Matt Jaffee
bbb93abd57
remove lots of unused code 2018-07-05 15:35:32 -05:00
Cody Soyland
da4cd84820 Remove some dead code 2018-07-05 15:31:07 -05:00
Matt Jaffee
e76a90e69b
change Query and QueryNode to use pilosa.* Query structs 2018-07-05 15:02:33 -05:00
Alan Bernstein
36926bdc47 WIP syntax and API updates 2018-07-05 14:52:30 -05:00
Matt Jaffee
59e80f9692
put Serializer on API, add QueryRequest/Response to serializer 2018-07-05 13:35:14 -05:00
Matt Jaffee
6309d3b7f7
get gossip using serializer stuff, remove proto and internal 2018-07-05 12:32:49 -05:00
Matt Jaffee
2cec75e399
add proto encoding subpackage and use for send and receive message 2018-07-05 12:00:42 -05:00
Alan Bernstein
e9503a443e Begin updating frame->field and slice->shard 2018-07-05 10:27:49 -05:00
Matt Jaffee
1b2aaa26bf
export NodeEvent 2018-07-05 09:26:58 -05:00
Travis Turner
3b898bf801
Merge pull request #1457 from travisturner/remove-dead-code
remove some dead code highlighed by the unexport script
2018-07-05 08:40:54 -05:00
Travis Turner
dd0e1c57bd
Merge branch 'develop' into remove-dead-code 2018-07-05 08:21:58 -05:00
Travis Turner
f59fa51a7e
Merge pull request #1458 from travisturner/unexport-fieldoptions
Un-export FieldOptions
2018-07-05 08:20:17 -05:00
Travis Turner
bae5ee36ef
add support for OptFieldKeys() to http field creation 2018-07-04 22:24:05 -05:00
Matt Jaffee
d2ec463b4e
Merge branch 'core-structs' of github.com:jaffee/pilosa into core-structs 2018-07-04 21:45:28 -05:00
Matt Jaffee
cd8c63c125
tests passing 2018-07-04 21:43:18 -05:00
Travis Turner
3e288aa391
un-export field.FieldOptions 2018-07-04 21:39:01 -05:00
Travis Turner
44f0b992f6
change all CreateField() methods to take functional options instead of FieldOptions 2018-07-04 21:22:35 -05:00
Matt Jaffee
6417f468bb
wip implement more... still quite broken 2018-07-04 16:50:20 -05:00
tgruben
342779051a
Merge branch 'develop' into core-structs 2018-07-04 12:28:18 -05:00
Travis Turner
1fb8330c8c
remove some dead code highlighed by the unexport script 2018-07-04 12:27:42 -05:00
Travis Turner
e7653928ec
Merge pull request #1456 from travisturner/fix-test-filenames
rename internal_tests. fix license header
2018-07-04 11:52:59 -05:00
Travis Turner
f526f18d82
rename internal_tests. fix license header 2018-07-04 10:59:08 -05:00
Matthew Jaffee
43020cf63c
Merge pull request #1453 from jaffee/1445-pql-fix
support newlines in more places
2018-07-04 09:51:18 -05:00
Matt Jaffee
4ef8fff9b6
WIP, broken. refactoring to isolate intneral structs and define core structs 2018-07-04 07:29:16 -05:00
Matt Jaffee
7900e47f8a
Merge branch 'develop' into remove-setupserver-calls 2018-07-03 16:33:32 -05:00
Matt Jaffee
6865dea4a1
Merge branch 'develop' into 1445-pql-fix 2018-07-03 16:32:27 -05:00
Matthew Jaffee
f3171a084c
Merge pull request #1452 from jaffee/gossip-use-api
make gossip's interface to Pilosa the API struct rather than effectiv…
2018-07-03 16:30:04 -05:00
Matt Jaffee
f757e10255
support newlines in more places 2018-07-03 16:28:51 -05:00
Matt Jaffee
5ff77c816a
get rid of unecessary server stuff and export node and uri 2018-07-03 13:26:51 -05:00
Matt Jaffee
f6aef32093
make gossip's interface to Pilosa the API struct rather than effectively being pilosa.Server 2018-07-03 12:58:18 -05:00
Matt Jaffee
3781b6e7eb
remove redundant calls to SetupServer 2018-07-03 11:05:33 -05:00
Matthew Jaffee
1af25172fc
Merge pull request #1450 from jaffee/unexport-index-stuff
Unexport index stuff
2018-07-03 11:03:26 -05:00
Matt Jaffee
bc0fce99d5
fix MustSetBit and cleanup dead code 2018-07-03 08:53:16 -05:00
Matt Jaffee
91622684cf
Merge branch 'develop' into unexport-index-stuff 2018-07-03 08:17:07 -05:00
Matt Jaffee
06ad83b64b
more unexports - index methods and fields 2018-07-03 08:10:33 -05:00
Matthew Jaffee
54dbb42661
Merge pull request #1449 from jaffee/unexport-view-stuff
Unexport view stuff
2018-07-03 08:04:17 -05:00
Matt Jaffee
f78af41565
unexport cluster's newhasher func 2018-07-02 17:25:21 -05:00
Matt Jaffee
197f491b29
unexport ViewPath 2018-07-02 17:24:02 -05:00
Matt Jaffee
78f4e131fc
Merge branch 'develop' into unexport-view-stuff 2018-07-02 17:18:38 -05:00
Matt Jaffee
2202bf467b
unexport view stuff 2018-07-02 17:18:00 -05:00
Matthew Jaffee
fe80b92e9a
Merge pull request #1448 from jaffee/unexport-cache-stuff
Unexport cache stuff
2018-07-02 17:17:48 -05:00
Matt Jaffee
5a9802c3b7
get rid of test.Holder.ViewRow, replace with more restricted RowTime 2018-07-02 17:08:33 -05:00
Matt Jaffee
62e0d185dc
unexport iterator stuff and make NopInternalClient less pointery 2018-07-02 15:22:51 -05:00
Matt Jaffee
de138f690b
Merge branch 'develop' into unexport-cache-stuff 2018-07-02 15:05:53 -05:00
Matthew Jaffee
1130c15ce7
Merge pull request #1447 from jaffee/unexport-fragment-stuff
Unexport fragment stuff
2018-07-02 15:05:30 -05:00
Matt Jaffee
712404b4ec
clean up nopCache 2018-07-02 15:05:00 -05:00
Matt Jaffee
65700f9604
unexport a bunch of cache.go stuff 2018-07-02 14:58:17 -05:00
Matt Jaffee
28ff31d4fc
Merge branch 'develop' into unexport-fragment-stuff 2018-07-02 14:51:26 -05:00
Matt Jaffee
cff01f46c2
unexport fragment.go stuff 2018-07-02 14:50:33 -05:00
Matthew Jaffee
f2be368222
Merge pull request #1446 from jaffee/unexport-holder-stuff
Unexport holder stuff
2018-07-02 14:45:47 -05:00
Matt Jaffee
009242fef9
unexport more Holder stuff (gorename) 2018-07-02 14:07:06 -05:00
Matt Jaffee
9995b0032e
unexport Holder.Fragment, HolderSyncer and HolderCleaner 2018-07-02 14:00:31 -05:00
Matt Jaffee
a6a0c6a7c3
unexport Holder.view and prepare to unexport Holder.Fragment 2018-07-02 13:58:20 -05:00
Travis Turner
1f3d22b5f6
Merge pull request #1444 from travisturner/http-endpoints
consolidate import and import-value endpoints
2018-07-02 11:13:35 -05:00
Travis Turner
9fd5ead7de
remove unused importValueNode() method 2018-07-02 10:41:54 -05:00
Travis Turner
2898a422bf
consolidate import and import-value endpoints 2018-07-02 10:41:54 -05:00
Matthew Jaffee
7bd55f47e7
Merge pull request #1443 from jaffee/field-unexport
work on unexporting View stuff
2018-07-02 10:38:11 -05:00
Matt Jaffee
c4797dcb0c
Merge branch 'develop' into field-unexport 2018-07-02 10:14:33 -05:00
Matt Jaffee
4182678d5a
work on unexporting View stuff 2018-07-02 10:11:56 -05:00
Matthew Jaffee
f84f98268f
Merge pull request #1440 from jaffee/even-more-unexport
Even more unexport
2018-07-02 09:57:27 -05:00
Matt Jaffee
d691e93ebc
Merge branch 'develop' into even-more-unexport 2018-07-02 09:39:35 -05:00
Travis Turner
0fdd13da0b
Merge pull request #1441 from travisturner/http-endpoints
move internal http endpoints under /internal
2018-07-02 09:32:25 -05:00
Matt Jaffee
7376befddd
Merge branch 'develop' into even-more-unexport 2018-07-02 09:12:30 -05:00
Matt Jaffee
3be609ed10
unexport newCluster and some other stuff 2018-07-02 09:10:09 -05:00
Travis Turner
cba91be126
move internal http endpoints under /internal 2018-07-02 08:48:23 -05:00
Travis Turner
309ced8ef7
Merge pull request #1433 from travisturner/http-responses
consolidate http errors into a shared response type
2018-07-02 08:45:35 -05:00
Travis Turner
0dca89ca4f
Merge branch 'develop' into http-responses 2018-07-02 08:37:37 -05:00
Matt Jaffee
a7bee851a4
Merge branch 'develop' into even-more-unexport 2018-07-02 08:37:21 -05:00
Matthew Jaffee
34e24af5ed
Merge pull request #1439 from jaffee/unexport-more-stuff
more unexports - executor, api fields
2018-07-02 08:35:26 -05:00
Matt Jaffee
9ea300da20
unexport broadcaster 2018-07-02 08:34:58 -05:00
Matt Jaffee
7ec9c97e46
fixup nopAttrStore.
Methods no longer take pointer receiver, and NewNopAttrStore always returns a
reference to the same global object (which is no longer exported).
2018-07-02 08:30:48 -05:00
Matt Jaffee
2210480198
unexport some translation related consts, remove an unused one 2018-07-02 08:20:53 -05:00
Matt Jaffee
91f531f2cd
more unexports - executor, api fields 2018-07-02 08:14:13 -05:00
Matthew Jaffee
253a90db52
Merge pull request #1438 from jaffee/unexport-cluster
unexport cluster (gorename)
2018-07-02 08:07:35 -05:00
Matt Jaffee
7801b81b10
unexport cluster (gorename) 2018-07-02 07:56:51 -05:00
Matthew Jaffee
b57304ebae
Merge pull request #1432 from jaffee/deadcode
Deadcode
2018-07-02 06:51:06 -05:00
Travis Turner
c0b5ad316d
use constructors for errors 2018-07-01 19:54:10 -05:00
Travis Turner
9633e34300
address feedback in PR 2018-07-01 19:54:10 -05:00
Travis Turner
3adc3f5978
add tests for index and field success responses 2018-07-01 19:54:09 -05:00
Travis Turner
8a5f5dd737
return an error when deleting a non-existent index or field 2018-07-01 19:54:09 -05:00
Travis Turner
7dd1f50a75
consolidate http errors into a shared response type 2018-07-01 19:54:09 -05:00
Matthew Jaffee
d012f254c9
Merge branch 'develop' into deadcode 2018-07-01 19:28:56 -05:00
Matthew Jaffee
ea18d06780
Merge pull request #1437 from jaffee/more-test-refactoring
remove the last usages of test.NewExecutor and cleanup unused in test…
2018-07-01 19:28:36 -05:00
Matt Jaffee
935aaa96f6
Merge branch 'develop' into deadcode 2018-07-01 12:18:28 -05:00
Matt Jaffee
95547a9a27
remove the last usages of test.NewExecutor and cleanup unused in test package 2018-07-01 07:31:31 -05:00
Matthew Jaffee
96eae99d38
Merge pull request #1434 from jaffee/skipped-tests
Skipped tests
2018-07-01 07:13:58 -05:00
Matt Jaffee
9337efc595
Merge branch 'develop' into skipped-tests 2018-06-30 08:43:19 -05:00
Matt Jaffee
29ad1287d4
refactor executor_test.go 2018-06-30 08:41:19 -05:00
tgruben
9755a186e1
Merge pull request #1435 from tgruben/quantum-test
more comprehensive time quantum tests
2018-06-29 17:52:24 -05:00
tgruben
3e44ab90c7
Merge branch 'develop' into quantum-test 2018-06-29 17:41:10 -05:00
Todd Gruben
785adfec2a more complete permutations 2018-06-29 17:35:40 -05:00
Cody Soyland
9ee4716267
Merge pull request #1429 from codysoyland/enterprise-license-exclude-apache
Exclude Apache2 license from enterprise build directory
2018-06-29 16:42:28 -04:00
tgruben
49ed3b71eb
Merge branch 'develop' into quantum-test 2018-06-29 15:37:01 -05:00
Todd Gruben
3db1087bce more comprehensive time quantum tests 2018-06-29 15:33:23 -05:00
Matt Jaffee
ea77db895a
fix syncholder test and a few bugs
The http internal client's FragmentBlocks and Blockdata methods were being used
incorrectly, and incorrect respectively. One was not being passed a node URI by
monitorAntiEntropy, and the other was always using the defaultURI regardless of
what was passed to it. Antientropy was doubling not working because of this. I
think this crept in pretty recently, so hasn't actually affected anyone.

I exposed a SyncData method on Server so that we can invoke the anti entropy
task manually instead of trying to set up the interval so that it will run and
then sleeping and waiting for it to run. Now that this test works the way it
does, the other anti entropy test is obsolete, and I deleted it.
2018-06-29 14:48:13 -05:00
Matt Jaffee
5766f572b1
fix skipped client TopN test
had to remove the first check which was for the wrong result - because maxShard
is no longer wrong since the broadcaster is actually working.
2018-06-29 12:21:33 -05:00
Matt Jaffee
6bb5bf2602
Merge branch 'develop' into deadcode 2018-06-29 10:11:56 -05:00
Cody Soyland
77c7a94686
Merge branch 'develop' into enterprise-license-exclude-apache 2018-06-29 09:46:46 -05:00
Matthew Jaffee
a1cb4ee107
Merge pull request #1431 from jaffee/1430-mapsize-overflow
define map size separately for 32 and 64 bit systems
2018-06-29 09:43:33 -05:00
Matt Jaffee
d73ff9bfe2
collapse memAttrStore
memAttrStore is not used, but I opted to leave it in order to encourage its use
by future unit tests. Since it is unexported, however, and its fairly obvious
what it does, I didn't think the docstrings were adding much value, and it's more
readable in this compact form.
2018-06-29 08:12:20 -05:00
Matt Jaffee
6ff792c164
remove dead code (deadcode) 2018-06-29 08:12:04 -05:00
Matt Jaffee
4124bc76a3
define map size separately for 32 and 64 bit systems 2018-06-29 07:18:26 -05:00
Matthew Jaffee
0fae552577
Merge pull request #1428 from jaffee/more-gossip-stuff
More gossip stuff
2018-06-29 07:14:41 -05:00
Matt Jaffee
d2d84d2649
remove commented code 2018-06-29 06:52:29 -05:00
Matt Jaffee
2e15db7ce0
Merge branch 'develop' into more-gossip-stuff 2018-06-29 06:49:13 -05:00
Cody Soyland
92466fda8d Remove Apache2 license from enterprise build directory 2018-06-28 21:59:15 -05:00
Cody Soyland
c75b85d9c1
Merge pull request #1427 from codysoyland/remove-api-broadcaster
Remove API.Broadcaster
2018-06-28 21:21:26 -05:00
Matt Jaffee
91454a5cd0
collapse *handler interfaces into MemberServer
gossip now takes a single "MemberServer" which is implemented by server. Several
interfaces have been removed.

MemberServer contains ReceiveMessage which is a superset of the functionality of
ReceiveEvent, LocalStatus and HandleRemoteStatus are all that's left of
StatusHandler -  ClusterStatus was not used and is gone. The Node() method is
actually a subset of LocalStatus() functionality. Maybe we should break up
localstatus or remove Node... not sure.

Remove BroadcastReceiver test which was a bit silly.

NodeEvent can now be unexported, and is.
2018-06-28 17:16:08 -05:00
Cody Soyland
86b24e3824 Remove API.Broadcaster 2018-06-28 15:51:51 -05:00
Travis Turner
e7acf21107
Merge pull request #1426 from travisturner/slice-to-shard
rename slice to shard
2018-06-28 15:43:33 -05:00
Travis Turner
e17096328d
Merge branch 'develop' into slice-to-shard 2018-06-28 15:38:40 -05:00
tgruben
bc5fec246c
Merge pull request #1424 from tgruben/clearbit-notime
Clearbit for time fields
2018-06-28 15:25:56 -05:00
Matt Jaffee
12a49c3e14
remove ClusterStatus method and StatusHandler interface
gossipEventReceiver uses ReceiveMessage instead of ReceiveEvent
2018-06-28 14:45:20 -05:00
Todd Gruben
4054f33ad5 exported DefaultCacheSize, not sure why i had unexproted 2018-06-28 14:40:23 -05:00
tgruben
a81e01b019
Merge branch 'develop' into clearbit-notime 2018-06-28 14:12:29 -05:00
Travis Turner
5dd7a9556a
rename slice to shard 2018-06-28 14:07:07 -05:00
Cody Soyland
112e8e68b6
Merge pull request #1425 from codysoyland/enhance-test-utilities
Enhance test utilities
2018-06-28 13:45:39 -05:00
Cody Soyland
4f3cf9af30 Use GossipAddress() helper 2018-06-28 13:34:58 -05:00
Cody Soyland
824474160e Enhance test utilities (introduce Cluster type, improve naming) 2018-06-28 13:34:58 -05:00
Todd Gruben
dde8ea02b1 Merge branch 'clearbit-notime' of github.com:tgruben/pilosa into clearbit-notime 2018-06-28 12:42:35 -05:00
Todd Gruben
fcecb871cf naming adjustments; code cleanup 2018-06-28 12:41:39 -05:00
Cody Soyland
0469cd599e
Merge pull request #1423 from codysoyland/fix-races
Fix a few data races
2018-06-28 12:22:29 -05:00
Cody Soyland
d629c59f58
Merge branch 'develop' into fix-races 2018-06-28 11:55:18 -05:00
Matt Jaffee
75c1440eb5
simplify gossipEventReceiver - no longer needs separate Start method
also remove some dead code
2018-06-28 11:25:07 -05:00
Matt Jaffee
965bd08225
unexport newGossipEventReceiver and remove some dead code 2018-06-28 11:00:45 -05:00
Cody Soyland
25be5c0f2f Use channel to notify on server close instead of atomic.Value. Ensure CloseFunc() only called once. 2018-06-28 10:38:37 -05:00
Matt Jaffee
09adc3b461
unexport gossipEventRecevier in gossip.go 2018-06-28 10:34:42 -05:00
Travis Turner
de93477e99
Merge pull request #1409 from travisturner/field-options
prepare to un-export pilosa.FieldOptions
2018-06-28 10:32:33 -05:00
Travis Turner
22661f3571
Merge branch 'develop' into field-options 2018-06-28 10:20:17 -05:00
tgruben
a8418b6c49
Merge branch 'develop' into clearbit-notime 2018-06-27 18:21:27 -05:00
Todd Gruben
4970083d4d refactored strategy for time based clearbit 2018-06-27 18:15:44 -05:00
Cody Soyland
5d43d414f7 Fix a few data races 2018-06-27 17:00:17 -05:00
Matthew Jaffee
f59452a7e7
Merge pull request #1421 from jaffee/remove-
remove some unused interfaces and implementations from broadcast.go
2018-06-27 16:15:20 -05:00
Matt Jaffee
648cfe7ad0
unexport Cluster fields which could be automatically unexported 2018-06-27 15:39:12 -05:00
Matt Jaffee
d6029e64fc
remove EventReceiver - not used anymore 2018-06-27 15:33:53 -05:00
Matt Jaffee
5e48023565
remove some unused interfaces and implementations from broadcast.go 2018-06-27 14:48:07 -05:00
Matthew Jaffee
7f908fcf38
Merge pull request #1420 from jaffee/remove-cluster-refs
Remove cluster refs
2018-06-27 14:35:36 -05:00
Cody Soyland
27de0e1682
Merge branch 'develop' into remove-cluster-refs 2018-06-27 14:22:49 -05:00
Cody Soyland
badb5bcc68
Merge pull request #1416 from codysoyland/unexport-api-translatestore
Remove API.TranslateStore
2018-06-27 14:22:18 -05:00
Cody Soyland
8657eb3b04
Merge branch 'develop' into unexport-api-translatestore 2018-06-27 14:07:46 -05:00
Matthew Jaffee
c0b13337f6
Merge pull request #1418 from jaffee/test-runcluster-simplify
Test runcluster simplify
2018-06-27 14:07:13 -05:00
Cody Soyland
b2ebb4ce06 Fix deadlock 2018-06-27 13:50:48 -05:00
Matt Jaffee
8f7cc2fbaa
unexport Server.LoadNodeID (gorename) 2018-06-27 13:37:08 -05:00
Matt Jaffee
9998eda3d4
remove Server.Addr - use URI instead 2018-06-27 13:37:08 -05:00
Matt Jaffee
8f5d154b6c
unexport Server.NodeID 2018-06-27 13:37:07 -05:00
Matt Jaffee
f3aa141409
unexport server.Cluster (gorename) 2018-06-27 13:37:07 -05:00
Matt Jaffee
ea448fee9c
remove remaining external references to Server.Cluster 2018-06-27 13:37:07 -05:00
Cody Soyland
c042c77499 Merge branch 'develop' into unexport-api-translatestore 2018-06-27 13:36:19 -05:00
Matt Jaffee
4b09de0ca0
Merge branch 'develop' into test-runcluster-simplify 2018-06-27 13:36:08 -05:00
Cody Soyland
ebfbf78cc5
Merge pull request #1419 from codysoyland/fix-translatestore-test
Fix TestTranslateStore_Reader tests
2018-06-27 13:34:55 -05:00
Cody Soyland
8d908a89ce Fix TestTranslateStore_Reader tests 2018-06-27 11:39:10 -05:00
Matt Jaffee
fbe035ef25
simplify test cluster setup by exposing gossip transport on server.Command 2018-06-27 10:46:37 -05:00
Matt Jaffee
41bdfceb57
remove MemberSet from cluster, Open in server package 2018-06-27 07:22:32 -05:00
Matthew Jaffee
a0f21064ed
Merge pull request #1417 from jaffee/extracting-memberset
continue simplifying memberset and pilosa setup
2018-06-27 07:21:27 -05:00
Matt Jaffee
c312bc1316
simplify arguments to NewGossipMemberSet 2018-06-27 07:18:16 -05:00
Matt Jaffee
7153499c6a
Merge branch 'develop' into extracting-memberset 2018-06-27 06:58:33 -05:00
Travis Turner
6ab2729f0c
Merge branch 'develop' into field-options 2018-06-26 23:39:42 -05:00
Yuce Tekol
ec6fa268c7
Merge pull request #1390 from yuce/update-getting-started
Updated getting started section for latest develop
2018-06-27 01:52:14 +03:00
Yuce Tekol
345165e7df
Merge branch 'develop' into update-getting-started 2018-06-27 01:16:05 +03:00
Yuce Tekol
ffaddb7e41
Merge branch 'develop' into update-getting-started 2018-06-27 01:15:35 +03:00
Matt Jaffee
bcb6942c80
continue simplifying memberset and pilosa setup
since the gossip MemberSet has access to Server, it wasn't really necessary to
pass it a Node object when calling Open on it from Cluster. The end goal is to
have it be removed from Cluster entirely, and have it be Opened externally, and
this is a step toward that.

Exposing Node method on Server doesn't really expose any more than was already
there as the same info can be gotten from LocalStatus with a bit of type
casting. I figured adding the method was a little cleaner, and we could collapse
all the functionality when the dust has settled.

The Cluster.open method has been broken into two parts - one of which happens
earlier (at NewServer time), and the other will eventually just be "waiting to
make sure we've joined the cluster". Right now it's calling Memberset.Open, and
then waiting to make sure the cluster has been joined.
2018-06-26 14:36:05 -05:00
Todd Gruben
f16426b50a Merge remote-tracking branch 'upstream/develop' into clearbit-notime 2018-06-26 13:24:06 -05:00
Matthew Jaffee
a5f9236f3a
Merge pull request #1410 from pilosa/fix-translate-merged
Fix translate merged
2018-06-26 13:11:35 -05:00
Matt Jaffee
d9b4cfacb0
Merge branch 'develop' into fix-translate-merged 2018-06-26 12:51:41 -05:00
Matthew Jaffee
83405b3d38
Merge pull request #1412 from jaffee/simplify-event-receiver
consolidate gossipEventReceiver into gossip member set
2018-06-26 12:50:00 -05:00
Todd Gruben
ddf1ffc797 Merge branch 'develop' into clearbit-notime 2018-06-26 12:35:30 -05:00
Cody Soyland
80f794a4fd Remove API.TranslateStore, refactor Handler.getTranslateData to use new helper API.GetTranslateData 2018-06-26 11:58:27 -05:00
Matt Jaffee
3314a0372c
Merge branch 'develop' into simplify-event-receiver 2018-06-26 11:45:14 -05:00
Matthew Jaffee
6e89abb8ed
Merge pull request #1413 from codysoyland/command-server-opts
Add CommandOptions and use OptCommandServerOptions to inject mock TranslateStore
2018-06-26 11:44:49 -05:00
Cody Soyland
2fa20197a5
Merge branch 'develop' into command-server-opts 2018-06-26 11:32:41 -05:00
Matt Jaffee
7190fe71e5
fix comment 2018-06-26 11:23:31 -05:00
Cody Soyland
533de70cbd Allow passing slice of CommandOptions to MustRunMainWithCluster, each slice going to one Command 2018-06-26 11:22:48 -05:00
Todd Gruben
35af580183 expanded views to contain viewType for special handling 2018-06-26 10:54:06 -05:00
Travis Turner
034e370602
Merge branch 'develop' into field-options 2018-06-26 10:51:50 -05:00
Travis Turner
028e95d914
Allow a single functional option for field options.
Move field type specific validation to functional options.
2018-06-26 10:37:56 -05:00
Cody Soyland
e448d47004 Store commandOptions on test.Main for use in Reopen(); unexport serverOptions 2018-06-26 08:47:31 -05:00
Matt Jaffee
c75c52d54b
Merge branch 'develop' into fix-translate-merged 2018-06-26 07:53:31 -05:00
Matt Jaffee
ee37152cd5
consolidate gossipEventReceiver into gossip member set
pilosa.Server now implements StatusHandler and EventReceiver and needs only
start a gossip memberset. A gossip member set now takes a server as an argument
explicitly and the maze of handlers and receivers and the starting sequence is
somewhat simplified.

Server now trivially implements EventHandler by passing the call along to its
Cluster object which has the actual implementation. This means that less things
will need to refer to cluster.
2018-06-26 07:50:33 -05:00
Matthew Jaffee
e667aede06
Merge pull request #1415 from pilosa/1414-frame-dash
allow dashes in frame names
2018-06-26 07:48:01 -05:00
Matt Jaffee
4ab9c66070
allow dashes in frame names 2018-06-26 07:00:13 -05:00
Cody Soyland
ff7c3cb512
Merge branch 'develop' into command-server-opts 2018-06-25 19:42:22 -05:00
Cody Soyland
9f68ea4663 Use OptCommandServerOptions to inject mock TranslateStore 2018-06-25 17:22:34 -05:00
Matt Jaffee
de702dab1e
Merge branch 'develop' into fix-translate 2018-06-25 16:02:12 -05:00
Travis Turner
50794bf63b
move fieldOptions unmarshal to the handler
validate fieldOptions in http package
2018-06-25 15:14:22 -05:00
Cody Soyland
a8a2be4bf4
Merge pull request #1411 from codysoyland/api-field-removal
Remove redundant fields from API
2018-06-25 15:10:50 -05:00
Cody Soyland
324028a8c2 Add ability to pass ServerOptions when calling NewCommand 2018-06-25 15:09:36 -05:00
Cody Soyland
790d565890 Remove redundant fields from API (a few remain due to test overrides) 2018-06-25 13:46:50 -05:00
Matt Jaffee
bb33411c5d
remove debugging print statement 2018-06-25 12:40:46 -05:00
Matt Jaffee
288ec9cb83
Merge branch 'develop' into fix-translate 2018-06-25 12:39:53 -05:00
Matt Jaffee
b2dd9c50ca
Merge branch 'develop' into fix-translate 2018-06-25 12:33:52 -05:00
Travis Turner
56f8b92257
Merge pull request #1408 from travisturner/check-header
add wildcard checks to checkHeaderAcceptJSON()
2018-06-25 11:48:43 -05:00
Travis Turner
2e035ee837
Merge branch 'develop' into check-header 2018-06-25 11:41:07 -05:00
Travis Turner
27e6dcea2b
rename checkHeaderAcceptJSON to validHeaderAcceptJSON and reverse boolean logic 2018-06-25 11:26:23 -05:00
Matthew Jaffee
5160ed58f7
Merge pull request #1407 from pilosa/wip-api-refactor
api refactor
2018-06-25 11:26:05 -05:00
Matt Jaffee
8878b02345
cleanup - address review feedback 2018-06-25 11:08:00 -05:00
Travis Turner
9d3332929d
add wildcard checks to checkHeaderAcceptJSON() 2018-06-24 22:45:35 -05:00
Matt Jaffee
6093064ac0
remove unecessary test and convert import test 2018-06-22 16:26:45 -05:00
tgruben
41a878f8a8
Merge pull request #1405 from tgruben/back-fix
backport fix for issue #1400
2018-06-22 14:52:44 -05:00
Todd Gruben
df492090b0 backfill fix for issue #1400 2018-06-22 14:32:42 -05:00
Matt Jaffee
c9e6d36f94
fix some of the client tests 2018-06-22 13:44:50 -05:00
Matt Jaffee
5d28d2dc31
skip new tests which use test.NewServer 2018-06-22 13:00:52 -05:00
Matt Jaffee
ba9112507d
fix server/handler_test.go for newpql 2018-06-22 12:57:28 -05:00
Matt Jaffee
7a5adf7428
Merge branch 'develop' into wip-api-refactor 2018-06-22 12:46:19 -05:00
Matthew Jaffee
c1f11d40e4
Merge pull request #1382 from pilosa/newpql
Newpql
2018-06-22 12:41:44 -05:00
Matt Jaffee
f5d62de0a2
Merge branch 'develop' into newpql 2018-06-22 12:26:20 -05:00
tgruben
bc46d379b7
Merge pull request #1401 from tgruben/crash-value-overwrite
Fix for Crash
2018-06-22 11:19:57 -05:00
Matt Jaffee
6b57369b51
fix stats tests 2018-06-22 10:44:36 -05:00
Cody Soyland
6dd8b9adc6 Move server initialization to prevent race condition 2018-06-22 10:22:13 -05:00
Todd Gruben
20c8247dc5 Merge branch 'crash-value-overwrite' of github.com:tgruben/pilosa into crash-value-overwrite 2018-06-22 10:06:44 -05:00
Todd Gruben
22a546095a fixed reset method on btree plugin 2018-06-22 10:05:41 -05:00
Yuce Tekol
7aff2173bd
Merge branch 'develop' into update-getting-started 2018-06-22 17:48:00 +03:00
Ben Johnson
8f3189c1b3
Translation fixes, error checking. 2018-06-22 08:12:35 -06:00
Matt Jaffee
80f5b13a97
Merge branch 'develop' into newpql 2018-06-22 09:11:00 -05:00
Matt Jaffee
d1de586ea0
remove all oldpql and fuzzer code 2018-06-22 09:08:08 -05:00
alanbernstein
406f008f80
Merge pull request #1402 from alanbernstein/pql-updates
Update to new PQL syntax beyond the parser
2018-06-22 08:42:26 -05:00
Alan Bernstein
ac66e51a1f Finish shell of OldPQL test 2018-06-22 08:36:03 -05:00
Alan Bernstein
35526dd0d7 Update to new PQL syntax beyond the parser 2018-06-22 08:11:27 -05:00
Matt Jaffee
3c4ba82a4a
finish conversion of handler tests 2018-06-22 08:08:53 -05:00
Alan Bernstein
5bf9af4df3 Parser and test updates 2018-06-22 08:07:31 -05:00
Matt Jaffee
8809751a23
convert all tests except for CORS 2018-06-22 07:41:39 -05:00
tgruben
4b72489997
Merge branch 'develop' into crash-value-overwrite 2018-06-21 20:10:54 -05:00
Matt Jaffee
016dbac6ca
convert a bunch more tests 2018-06-21 19:24:17 -05:00
Todd Gruben
643e5e575a fixed crashing issue that was not handling container removal/recycling correctly 2018-06-21 18:39:06 -05:00
Cody Soyland
e2512ec58d Use test.MustRunMainWithCluster in ctl tests 2018-06-21 16:26:34 -05:00
Cody Soyland
526bdae280 Remove unneccessary t.Skip() 2018-06-21 15:41:34 -05:00
Matt Jaffee
504309e594
rewrite some tests to not be skipped 2018-06-21 15:06:22 -05:00
Matt Jaffee
a033771412
move handler tests which are actually testing everything to server package 2018-06-21 14:05:00 -05:00
Matt Jaffee
c9479afe8c
start handler before server.Open to avoid stall in cluster.open
cluster.open waits for node to join cluster if it is not the coordinator, and
currently this relies on having the http handler able to receive messages, so
handler needs to be started first.
2018-06-21 13:56:46 -05:00
Cody Soyland
c6db3974bc WIP API refactor 2018-06-21 13:51:31 -05:00
tgruben
f3d9311d7f
Merge pull request #1399 from tgruben/accept-json
Accept json
2018-06-20 15:42:16 -05:00
Todd Gruben
d9369ed06e removed whitespace 2018-06-20 15:29:10 -05:00
Todd Gruben
5a3abe6f90 Merge branch 'accept-json' of github.com:tgruben/pilosa into accept-json 2018-06-20 15:12:55 -05:00
Todd Gruben
289bec9d81 repace panic with fatal for consistancy 2018-06-20 15:12:26 -05:00
tgruben
6c389e08cd
Merge branch 'develop' into accept-json 2018-06-20 15:08:13 -05:00
Todd Gruben
7da9242b6b error only on if provided accept not json 2018-06-20 14:39:15 -05:00
Matthew Jaffee
79175b1398
Merge pull request #1398 from jaffee/broadcaster-remove
remove broadcaster from server
2018-06-20 13:41:08 -05:00
Todd Gruben
ff81322d69 Merge remote-tracking branch 'upstream/develop' into accept-json 2018-06-20 13:14:37 -05:00
Todd Gruben
aac2397949 enforced Accept for json response endpoints 2018-06-20 13:13:46 -05:00
Matt Jaffee
343880e0ad
remove broadcaster from server 2018-06-20 13:13:35 -05:00
Matthew Jaffee
57da20728e
Merge pull request #1397 from jaffee/server-cleanup
Server cleanup
2018-06-20 12:32:09 -05:00
Matt Jaffee
b271ff286c
unexport done channel on server.Command 2018-06-20 11:31:30 -05:00
Matt Jaffee
d529ee3ccc
unexport Server.TranslateFile 2018-06-20 11:26:33 -05:00
Matt Jaffee
44d3e87d4e
remove remaining external ref to Server.Holder and unexport holder 2018-06-20 11:21:03 -05:00
Matt Jaffee
7a05f32a17
remove NewAttrStore field on Server - unused 2018-06-20 11:14:09 -05:00
Matt Jaffee
1a2fa51b63
Merge branch 'develop' into newpql 2018-06-20 09:31:42 -05:00
Matt Jaffee
205b7620bd
update SetColumnAttrs name 2018-06-20 09:31:20 -05:00
Travis Turner
e94feba37e
Merge pull request #1396 from travisturner/remove-view-argument
remove view argument from Field.SetBit and Field.ClearBit
2018-06-19 21:17:47 -05:00
Travis Turner
b7470ba8a8
Merge branch 'develop' into remove-view-argument 2018-06-19 19:50:03 -05:00
Travis Turner
7eb5118ef0
Merge pull request #1394 from travisturner/simplify-addnode
simplify test cluster addNode signature
2018-06-19 19:49:16 -05:00
Matthew Jaffee
ddb2963dd4
Merge branch 'develop' into remove-view-argument 2018-06-19 19:44:07 -05:00
Travis Turner
15b5e5241e
Merge branch 'develop' into simplify-addnode 2018-06-19 19:29:00 -05:00
Matthew Jaffee
7842dc4cce
Merge pull request #1393 from jaffee/move-static-setup
move static cluster setup logic into Server/Cluster
2018-06-19 19:23:41 -05:00
Matt Jaffee
6fb0519683
Merge branch 'develop' into move-static-setup 2018-06-19 19:18:23 -05:00
Travis Turner
c77b7d5ca5
remove view argument from Field.SetBit and Field.ClearBit 2018-06-19 18:15:38 -05:00
Travis Turner
a39b952748
Merge pull request #1395 from travisturner/frame-test
rename test/frame.go to test/field.go
2018-06-19 18:10:09 -05:00
Travis Turner
8c35cb89bb
rename test/frame.go to test/field.go 2018-06-19 17:54:16 -05:00
Travis Turner
ca6b3b5524
simplify test cluter addNode signature 2018-06-19 17:48:37 -05:00
Matt Jaffee
69b1f2ea97
make behavior equivalent to pre-change to stop test from failing 2018-06-19 17:02:44 -05:00
Matt Jaffee
33b3a14b24
move static cluster setup logic into Server/Cluster 2018-06-19 16:28:54 -05:00
tgruben
60eef02f31
Merge pull request #1392 from tgruben/addnode-ue
cleanup addnode unexport
2018-06-19 14:33:23 -05:00
Matt Jaffee
08e84aa07f
time range support 2018-06-19 14:07:03 -05:00
tgruben
819a29199e
Merge branch 'develop' into addnode-ue 2018-06-19 14:00:15 -05:00
Matthew Jaffee
1103039aa1
Merge pull request #1391 from pilosa/more-messaging-simplification
More messaging simplification
2018-06-19 13:55:46 -05:00
Todd Gruben
eb43707d19 cleanup 2018-06-19 13:34:44 -05:00
Matt Jaffee
719241f0d9
move some silly comments around 2018-06-19 13:22:08 -05:00
Matt Jaffee
f06c532047
remove a few unecessary lines from SetupNetworking
NewServer calls LoadNodeID, and NopBroadcaster and NopBroadcastReceiver are
already set up as the defaults.
2018-06-19 13:22:08 -05:00
tgruben
07480830da
Merge pull request #1365 from tgruben/slicecount-optimization
WIP count optimization
2018-06-19 11:11:19 -05:00
Todd Gruben
5048bbcaa2 Merge branch 'slicecount-optimization' of github.com:tgruben/pilosa into slicecount-optimization 2018-06-19 11:02:45 -05:00
Todd Gruben
aa71c08f12 implemented count optimization for btree 2018-06-19 11:01:00 -05:00
Todd Gruben
1488ac0e3a Merge branch 'develop' into slicecount-optimization 2018-06-19 10:36:05 -05:00
Yuce Tekol
80fadb5d21
Updated client libraries 2018-06-19 16:59:13 +03:00
Yuce Tekol
1e6d0a433e
Updated getting started section for latest develop 2018-06-19 16:19:36 +03:00
Matthew Jaffee
f591c4911e
Merge pull request #1389 from pilosa/remove-broadcaster-gossip
remove broadcaster methods from gossip- don't use sendAsync anywhere
2018-06-18 22:36:25 -05:00
Matt Jaffee
56ed9bfbe1
remove broadcaster methods from gossip- don't use sendAsync anywhere 2018-06-18 18:47:29 -05:00
Matthew Jaffee
6ef9b0bb93
Merge pull request #1388 from tgruben/issue-1283
added fields meta to index http endpoint
2018-06-18 14:45:41 -05:00
tgruben
f412f4d0c7
Merge branch 'develop' into issue-1283 2018-06-18 14:20:21 -05:00
Matthew Jaffee
b4c7c400e1
Merge pull request #1387 from pilosa/attr-test-cleanup
Attr test cleanup
2018-06-18 14:12:16 -05:00
Todd Gruben
18c67269ae clarity 2018-06-18 14:08:22 -05:00
Todd Gruben
07ab60d6cf adjust requirements to match schema response 2018-06-18 13:58:12 -05:00
Todd Gruben
277ee1e25e added fields meta to index http endpoint 2018-06-18 13:28:24 -05:00
Matthew Jaffee
18f159cf70
Merge branch 'develop' into attr-test-cleanup 2018-06-18 13:15:02 -05:00
Matthew Jaffee
2fc9f41806
Merge pull request #1386 from pilosa/client-test-cleanup
move pilosa/test/client.go helpers into pilosa/client_test.go
2018-06-18 13:14:38 -05:00
Matt Jaffee
60dee04ed1
move pilosa/test/attr.go into pilosa/attr_test.go 2018-06-18 12:52:58 -05:00
Matt Jaffee
9a74763156
move pilosa/test/client.go helpers into pilosa/client_test.go 2018-06-18 12:40:59 -05:00
Matt Jaffee
5c081d1518
more tests, fix bug where Condition wasn't pointer 2018-06-18 11:59:39 -05:00
Matt Jaffee
a6b6442ef4
more tests and fix range 2018-06-18 11:32:21 -05:00
Ben Johnson
c9ff679efc
Merge pull request #1337 from benbjohnson/translator
ID-Key Translation
2018-06-18 08:26:27 -06:00
Ben Johnson
060254e0d6
Key-to-ID Translation
This commit adds id-to-key translation to make it easier for users
to provide non-integer identifiers for rows & columns.
2018-06-15 16:45:05 -06:00
Matt Jaffee
23bca175ae
add tests, fix tests, fix bugs 2018-06-15 15:02:41 -05:00
Matt Jaffee
4b856bea55
change parser for new PQL 2018-06-15 12:22:16 -05:00
Matt Jaffee
1e05920742
fuzz testing and bug fixes 2018-06-15 08:34:14 -05:00
Matt Jaffee
2ddc2ceeeb
add old parser implementation to pql/internal/oldpql for comparison fuzz testing 2018-06-15 08:34:13 -05:00
Matt Jaffee
c66cb59f1d
remove -switch option from peg generator 2018-06-15 08:34:13 -05:00
Matt Jaffee
3656bc83a0
support quoted strings properly 2018-06-15 08:34:13 -05:00
Matt Jaffee
47233c8bee
replace PQL parser with one created by PEG parser generator 2018-06-15 08:34:12 -05:00
tgruben
9ad8d8d0b9
Merge pull request #1378 from tgruben/query-generator
add supporting functions for functional pql.Query construction
2018-06-14 11:55:00 -05:00
tgruben
bffa009fa7
Merge branch 'develop' into query-generator 2018-06-14 10:55:42 -05:00
Todd Gruben
aa21890503 moved to internal/test 2018-06-14 10:02:36 -05:00
Todd Gruben
b36b3b16ff moved to pilosa core 2018-06-14 09:12:05 -05:00
Cody Soyland
80712cf05f
Merge pull request #1377 from codysoyland/http-inversion-2
Remove more net/http references
2018-06-13 22:00:19 -05:00
Cody Soyland
415b4de110
Merge branch 'develop' into http-inversion-2 2018-06-13 21:38:30 -05:00
Travis Turner
6e804d8d51
Merge pull request #1374 from travisturner/global-consts
un-export package level consts
2018-06-13 19:23:10 -05:00
Travis Turner
7d91261968
un-export some package level constants 2018-06-13 17:18:52 -05:00
Travis Turner
70030305f2
Merge pull request #1372 from travisturner/global-functions
un-export some top-level functions
2018-06-13 17:09:21 -05:00
Cody Soyland
fba865fc6c Remove more net/http references 2018-06-13 16:50:44 -05:00
Travis Turner
fe167ea78c
un-export some top-level functions 2018-06-13 16:44:24 -05:00
Travis Turner
64103253aa
Merge pull request #1369 from travisturner/unexport-cluster-methods
un-export (some) Cluster methods
2018-06-13 16:11:14 -05:00
Todd Gruben
1211663019 add supporting functions for functional query contstruction 2018-06-13 15:47:00 -05:00
Travis Turner
8021fc389b
un-export (some) Cluster methods 2018-06-13 15:42:35 -05:00
Cody Soyland
ab652ebe7d
Merge pull request #1375 from codysoyland/http-inversion
Migrate HTTP handler and client into http subpackage
2018-06-13 09:38:00 -05:00
Cody Soyland
37153daf15 Remove commented code 2018-06-13 09:21:25 -05:00
Cody Soyland
952db994c7 Fix mistake in interface name 2018-06-13 09:21:15 -05:00
Cody Soyland
ecbbd31b4e Improve naming 2018-06-13 09:18:50 -05:00
Cody Soyland
daffa3b125 Rename InternalHTTPClient -> InternalClient 2018-06-13 09:04:04 -05:00
Cody Soyland
64287905bd Add missing argument to Errorf call 2018-06-13 08:56:14 -05:00
Cody Soyland
0b16a3afb9 Merge branch 'develop' into http-inversion 2018-06-12 14:49:54 -05:00
Cody Soyland
f2c104dfef Migrate HTTP handler and client into http subpackage. 2018-06-12 13:22:40 -05:00
Travis Turner
f0b52d70f6
Merge pull request #1367 from travisturner/unexport-view-methods
unexport (most) View methods
2018-06-08 13:10:20 -05:00
Travis Turner
e58d407182
unexport (most) View methods 2018-06-07 22:50:49 -05:00
Travis Turner
73ace979e3
Merge pull request #1366 from travisturner/unexport-fragment
Unexport (some) fragment methods
2018-06-07 22:12:14 -05:00
Travis Turner
173939813f
remove slice argment from Field.Row() method 2018-06-07 17:14:46 -05:00
Travis Turner
38ae5b19f7
remove commented code 2018-06-07 15:20:18 -05:00
Travis Turner
3c3c98371b
unexport Fragment.Row(). This required creating Field.Row() and View.row() 2018-06-07 15:09:58 -05:00
Travis Turner
468ad57b6d
un-export Fragment.SetBit and Fragment.ClearBit.
adds methods to test.Holder to set/clear bits on a field.
2018-06-07 13:43:20 -05:00
Travis Turner
15cb391570
first pass at un-exporting Fragment methods 2018-06-07 11:49:39 -05:00
tgruben
813cd06bee
Merge branch 'develop' into slicecount-optimization 2018-06-07 10:55:09 -05:00
Todd Gruben
89da69e6a5 WIP count optimization 2018-06-07 10:49:45 -05:00
Travis Turner
8d4cf1abf3
Merge pull request #1364 from travisturner/fragment-internal-tests
move fragment_test into the pilosa package (internal)
2018-06-06 16:29:26 -05:00
Travis Turner
6f4c50a4b5
move fragment_test into the pilosa package (internal) 2018-06-06 16:06:11 -05:00
Cody Soyland
14889326be
Merge pull request #1363 from codysoyland/webui-ectomy
Remove WebUI (now contained in a separate package)
2018-06-06 13:41:37 -05:00
Cody Soyland
34cea87683 Remove WebUI (now contained in a separate package)
It now lives at https://github.com/pilosa/webui
2018-06-06 11:44:31 -05:00
Travis Turner
f147630051
Merge pull request #1362 from travisturner/frame-to-field
Frame to field
2018-06-06 09:14:32 -05:00
Travis Turner
2a9b1e9e5b
final Frame to Field rename 2018-06-06 01:27:12 -05:00
Travis Turner
0f8bd62e33
more Frame to Field in tests. move frame*.go files to field*.go 2018-06-05 23:58:46 -05:00
Travis Turner
ba5d687ee0
finish frame to field in frame.go 2018-06-05 23:46:17 -05:00
Travis Turner
4e0aff0ca2
finish frame to field in api.go 2018-06-05 23:43:01 -05:00
Travis Turner
4c44c5f33a
fix Frame to Field in tests 2018-06-05 23:33:00 -05:00
Travis Turner
cb7487e34d
change all instances of internal Frame to Field 2018-06-05 23:24:24 -05:00
Travis Turner
636bf252ad
rename internal Frame to Field 2018-06-05 23:13:49 -05:00
Travis Turner
4254eb1d11
rename internal FrameMeta to FieldOptions 2018-06-05 23:10:59 -05:00
Travis Turner
6dbe80350f
GoRename Frame to Field in client.go 2018-06-05 23:02:15 -05:00
Travis Turner
b88ebfb754
GoRename Frame to Field in diagnostics.go 2018-06-05 22:52:57 -05:00
Travis Turner
7bb6d2b789
GoRename Frame to Field in fragment.go 2018-06-05 22:45:15 -05:00
Travis Turner
bbf3e529dc
GoRename Frame to Field in cluster.go 2018-06-05 22:42:21 -05:00
Travis Turner
bcec20525b
GoRename Frame to Field in view.go 2018-06-05 22:38:52 -05:00
Travis Turner
9db359d34a
GoRename Frame to Field in holder.go 2018-06-05 22:36:19 -05:00
Travis Turner
3531c128c4
GoRename Frame to Field in index.go 2018-06-05 22:33:48 -05:00
Travis Turner
1d3c4d6fcb
first pass at GoRename Frame to Field in frame.go 2018-06-05 17:52:22 -05:00
Travis Turner
2ed559e2bb
Merge pull request #1360 from travisturner/field-rename
Field rename
2018-06-05 17:04:25 -05:00
Travis Turner
80d656ae9c
final removal of field instances 2018-06-05 16:56:16 -05:00
Travis Turner
96208283df
remove final instances of Field 2018-06-05 16:38:29 -05:00
Travis Turner
383d6131f1
Merge pull request #1359 from travisturner/remove-import-field
remove field flag from pilosa import command
2018-06-05 16:28:56 -05:00
Travis Turner
0d44e586cc
remove field flag from pilosa import command 2018-06-05 16:14:26 -05:00
Travis Turner
3023d6fd37
Merge pull request #1358 from travisturner/rename-field-part-three
Remove frame argument from Range() queries.
2018-06-05 16:12:04 -05:00
Travis Turner
2802f6f469
remove frame argument from Range() queries 2018-06-05 15:09:41 -05:00
Travis Turner
386545c67c
rename TopN field/filters to attrName/attrValues 2018-06-05 14:33:26 -05:00
Travis Turner
2680c00dc9
Merge pull request #1357 from travisturner/rename-field-part-two
More renaming and removal of Field
2018-06-05 14:29:12 -05:00
Travis Turner
50f8ea3921
remove CreateField and DeleteField from API 2018-06-05 13:58:28 -05:00
Travis Turner
81a994987f
fixing some comments 2018-06-05 13:02:26 -05:00
Travis Turner
7f1ac8fdcd
remove Field* from fragment.go 2018-06-05 12:57:15 -05:00
Travis Turner
207e9c2674
minor fixes 2018-06-05 12:30:59 -05:00
Travis Turner
2111a3d521
more Field removal/rename 2018-06-05 11:13:51 -05:00
Travis Turner
28cdaa61e7
rename some instances of field to bsiGroup 2018-06-05 09:32:40 -05:00
Travis Turner
b566fd278a
remove field name argument from Frame.Value() 2018-06-05 09:32:39 -05:00
Travis Turner
127d7a7298
Merge pull request #1355 from travisturner/rename-field
Remove instances of Field
2018-06-05 09:31:05 -05:00
Travis Turner
51a42d3e35
rename test names 2018-06-04 17:40:25 -05:00
Travis Turner
d80d3b6d51
rename cases of Field in view.go 2018-06-04 17:33:55 -05:00
Travis Turner
a6ae39d0b0
remove cases of Field from frame.go 2018-06-04 17:33:55 -05:00
Travis Turner
dcf4daf24e
rename a lot of *Field cases to *BSIGroup 2018-06-04 17:33:55 -05:00
Travis Turner
b10463485e
rename Frame.Field() to Frame.bsiGroup() 2018-06-04 17:33:55 -05:00
Travis Turner
54d94f1aca
rename CreateField to createBSIGroup 2018-06-04 17:33:55 -05:00
Travis Turner
5d39ba25df
rename FieldTypeInt to bsiGroupTypeInt 2018-06-04 17:33:54 -05:00
Travis Turner
63e41b912b
rename Frame.fields to Frame.bsiGroups 2018-06-04 17:33:54 -05:00
Travis Turner
1f476c9078
rename oField to bsiGroup 2018-06-04 17:33:54 -05:00
Travis Turner
ac3a0b1eca
Merge pull request #1354 from travisturner/unexport-field-part-two
Rename SetFieldValue to SetValue
2018-06-04 16:46:16 -05:00
Travis Turner
dd6b80f90d
rename fragment.SetFieldValue() to fragment.SetValue(). Still exported for tests 2018-06-04 15:08:49 -05:00
Travis Turner
17c8944685
rename view.SetFieldValue() to view.setValue() 2018-06-04 15:08:49 -05:00
Travis Turner
c49fdb7b9b
rename executor.SetFieldValue() to executor.SetValue() 2018-06-04 15:08:49 -05:00
Travis Turner
90a4d957bd
remove frame argument from Frame.SetFieldValue(). Rename it to Frame.SetValue() 2018-06-04 15:08:48 -05:00
Travis Turner
6b9a0e871f
Merge pull request #1351 from travisturner/unexport-field
Unexport `field`
2018-06-04 14:59:05 -05:00
Travis Turner
17c7934473
un-export HasField. remove dead code 2018-06-04 14:45:28 -05:00
Travis Turner
dbb4cdf390
adjust the tests to match the new unexported Field and FrameOptions 2018-06-04 14:45:28 -05:00
Travis Turner
d799967fc6
add Type to frame so support BSI frame type "int" 2018-06-04 14:45:28 -05:00
Travis Turner
a60ff2d1e0
remove field from handler endpoints 2018-06-04 14:45:28 -05:00
Travis Turner
4edc80ea62
unexport Field 2018-06-04 14:45:27 -05:00
Matthew Jaffee
f802f3bc5c
Merge pull request #1350 from jaffee/generate-config-and-toml-fix
fix generate-config command, use single toml lib
2018-06-02 11:15:12 -05:00
Travis Turner
a6a121d19f
add toml tag to config.Handler 2018-06-02 09:59:11 -05:00
Matt Jaffee
c1c89b9ef8
fix generate-config command, use single toml lib
The generate-config command was printing a fixed string rather than calling
NewConfig() which is the canonical source for default config. I also noticed
that we were depending on two different toml libraries, and so collapsed that to
a single one. We have to use pelletier rather than BurntSushi because the viper
library that we use depends on pelletier.
2018-06-01 09:21:38 -05:00
Yuce Tekol
d79586a434
Merge pull request #1347 from yuce/1342-remove-bench
Removes bench command
2018-06-01 03:53:40 +03:00
Yuce Tekol
b3a4d02522
Merge branch 'develop' into 1342-remove-bench 2018-06-01 03:41:51 +03:00
Cody Soyland
1fb51afe60
Merge pull request #1348 from codysoyland/ci-speedup
Exclude/remove CI matrix configurations to speed up CI process
2018-05-31 11:11:47 -05:00
Cody Soyland
908066a650 Exclude/remove CI matrix configurations to speed up CI process. 2018-05-30 11:08:49 -05:00
Yuce Tekol
a04e5c8a9b
Merge pull request #1346 from yuce/1336-remove-views-from-api-docs
Remove view from API, handler, docs
2018-05-30 17:46:10 +03:00
Yuce Tekol
164b7619aa
Removes bench command 2018-05-30 16:40:21 +03:00
Yuce Tekol
738dead374
Remove view from API, handler, docs 2018-05-30 16:22:15 +03:00
Yuce Tekol
9456a2076d
Merge pull request #1341 from yuce/1319-more-removals
More backup/restore stuff removal
2018-05-30 09:14:52 +03:00
Yuce Tekol
dc75021e06
Merge branch 'master' into 1319-more-removals 2018-05-29 22:23:00 +03:00
Cody Soyland
22d48deebe
Merge pull request #1331 from yuce/update-tls-config
Match TLSConfig to the docs
2018-05-29 12:23:45 -05:00
Cody Soyland
e69be0b980
Merge branch 'master' into update-tls-config 2018-05-29 11:56:31 -05:00
Cody Soyland
201077b086
Merge pull request #1327 from codysoyland/cors-support
Add CORS support to handler
2018-05-29 11:54:38 -05:00
Cody Soyland
d50c2c9f72
Merge branch 'master' into cors-support 2018-05-29 11:38:54 -05:00
Yuce Tekol
998ebf43f9
Merge branch 'master' into update-tls-config 2018-05-29 19:01:51 +03:00
tgruben
2df58b6605
Merge pull request #1333 from tgruben/optimizeMax
simplified bitmap max function
2018-05-29 10:59:26 -05:00
Cody Soyland
31c4e18d8d
Merge branch 'master' into cors-support 2018-05-29 10:26:19 -05:00
tgruben
afc8d86161
Merge branch 'master' into optimizeMax 2018-05-29 10:07:47 -05:00
Cody Soyland
65f43c9a4d
Merge pull request #1340 from codysoyland/coveralls-removal
Remove coveralls from CI build
2018-05-29 09:48:02 -05:00
Yuce Tekol
5f2b587e7c
More backup/restore stuff removal 2018-05-29 16:44:57 +03:00
Cody Soyland
b8e4f721d7 Merge branch 'master' into coveralls-removal 2018-05-29 08:37:44 -05:00
Cody Soyland
2d06100bd2 Enable fast_finish (do not wait on allow_failures section to complete before marking complete. 2018-05-29 08:37:12 -05:00
Yuce Tekol
57ba900174
Merge pull request #1339 from yuce/1319-remove-backup-endpoint-t2
Removes backup/restore stuff
2018-05-29 16:28:54 +03:00
Cody Soyland
adcbb8fc2d Remove coveralls from CI build 2018-05-29 08:24:31 -05:00
Cody Soyland
77a5c6f811 Merge branch 'master' into cors-support 2018-05-29 08:18:26 -05:00
Yuce Tekol
82f2f14503
Removed backup/restore stuff 2018-05-28 16:54:32 +03:00
Yuce Tekol
70cc3303cc
removed restore endpoint 2018-05-28 16:52:55 +03:00
Matthew Jaffee
7510ff2baa
Merge pull request #1335 from jaffee/remove-inverse
Remove inverse
2018-05-25 20:12:48 -05:00
Matt Jaffee
a8795a7445
remove comments about views no longer applicable 2018-05-25 19:30:48 -05:00
Matt Jaffee
b3b29fad47
correct bug where slices were being ignored 2018-05-25 17:18:39 -05:00
Matt Jaffee
47f7beaecc
WIP removing inverse 2018-05-25 17:18:38 -05:00
tgruben
18b485cba1
Merge branch 'master' into optimizeMax 2018-05-25 16:58:42 -05:00
Matthew Jaffee
4a91a9f0a1
Merge pull request #1332 from jaffee/remove-rangeenabled
remove rangeEnabled option everywhere
2018-05-25 16:54:48 -05:00
Matt Jaffee
4767ea7bad
fix indentation issue 2018-05-25 14:34:25 -05:00
Todd Gruben
621e22d26c simplified bitmap max function 2018-05-25 14:24:46 -05:00
Matt Jaffee
75e8a873b1
remove rangeEnabled option everywhere 2018-05-25 13:09:32 -05:00
tgruben
63e440bb74
Merge pull request #1326 from tgruben/bitsToColumn
Change bits terminolgy to column
2018-05-25 11:44:40 -05:00
Matt Jaffee
1317d5e989
more bit/column comment tweaks 2018-05-25 11:02:14 -05:00
Matt Jaffee
ca530b1fc3
more fixes 2018-05-25 10:57:51 -05:00
tgruben
f7f20c6595
Merge branch 'master' into bitsToColumn 2018-05-25 10:42:32 -05:00
Matt Jaffee
b878ab347a
few more fixes to bsi comments 2018-05-25 10:23:14 -05:00
Yuce Tekol
ad29269a7f
Add tls tag 2018-05-25 16:03:53 +03:00
Yuce Tekol
5ee2c45d4a
Match TLSConfig to the docs 2018-05-25 10:41:42 +03:00
Yuce Tekol
5cc4e07df1
Merge pull request #1329 from yuce/update-clearbit-docs
ClearBit doc fix
2018-05-25 09:01:41 +03:00
Matt Jaffee
4ef266e5cc
revert a bunch of stuff and fix some comments 2018-05-24 16:35:27 -05:00
Cody Soyland
364bbfcf2c Add docs for handler.allowed-origins 2018-05-24 15:32:34 -05:00
Cody Soyland
1cbc626c1c Modify comments, change default on handler.allowed-origins 2018-05-24 15:32:09 -05:00
Todd Gruben
e3da6efe3c revert to old labels on BSI; revert MustSetColumns 2018-05-24 12:48:24 -05:00
Yuce Tekol
c3166fb0c1
ClerBit doc fix 2018-05-24 18:36:09 +03:00
Cody Soyland
1a9beb0916 Add CORS support to handler. 2018-05-24 08:42:34 -05:00
Todd Gruben
de4de2ba2e changed ExcludeAttr -> ExcludeRowAttr for clarity 2018-05-24 08:27:18 -05:00
Todd Gruben
fb7bf11825 Bit -> Column migration 2018-05-23 15:05:22 -05:00
Yuce Tekol
3943e3e3cb
Merge pull request #1305 from yuce/docker-swarm-tutorial
Docker swarm tutorial
2018-05-21 23:01:36 +03:00
tgruben
61164a5def
Merge pull request #1311 from tgruben/changeBitmapToRow
renamed pilosa.Bitmap to Row
2018-05-21 13:25:16 -05:00
Todd Gruben
5b2f8b4c33 migrated internal.Bitmap to internal.Row 2018-05-21 13:08:45 -05:00
Yuce Tekol
2a60f09c8c
updates 2018-05-21 20:32:27 +03:00
Todd Gruben
6d7178ca91 replaced some overlooked bm's 2018-05-21 12:13:15 -05:00
Todd Gruben
47b100e96b migrate BitmapSegment RowSegment 2018-05-21 11:44:51 -05:00
Todd Gruben
6f204e11f1 cleanup local variable naming and comments for Rows 2018-05-21 11:35:34 -05:00
Yuce Tekol
91df211be7
Updated docker swarm tutorial with required open ports 2018-05-21 19:25:19 +03:00
Todd Gruben
575e199ad8 renamed pilosa.Bitmap to Row 2018-05-21 09:12:42 -05:00
Matthew Jaffee
8e071df0c2
Merge pull request #1309 from jaffee/more-errors-cause
wrap switch errs in errors.Cause in handler
2018-05-18 16:02:54 -05:00
Matt Jaffee
1c850e51f2
wrap switch errs in errors.Cause in handler 2018-05-18 13:21:00 -05:00
Cody Soyland
2486fcefa1
Merge pull request #1307 from codysoyland/make-version-fix
Use lazy assignment for VERSION_ID so enterprise flag is set appropriately
2018-05-18 13:16:42 -05:00
Cody Soyland
f4bed7767d Use lazy assignment for VERSION_ID so enterprise flag is set appropriately. 2018-05-18 11:51:20 -05:00
Cody Soyland
4fe29827ac
Merge pull request #1302 from codysoyland/http-handler-close-redux
Close HTTP handler gracefully (Fixes #1018)
2018-05-18 09:29:10 -05:00
Travis Turner
316e657257
Merge pull request #1297 from travisturner/cluster-state-test-poll
adjust cluster state tests so they aren't so dependent upon a sleep
2018-05-18 09:03:53 -05:00
Yuce Tekol
8f79815f9b
Fixed the response in the docker swarm tut. 2018-05-18 16:44:57 +03:00
Yuce Tekol
89ece0e147
Added docker swarm tutorial 2018-05-18 16:41:45 +03:00
Matthew Jaffee
7aff846bc5
Merge pull request #1304 from jaffee/errcause-handler
use errors.Cause in handler so that we return correct status codes
2018-05-17 18:42:43 -05:00
Matt Jaffee
7a5608a93f
use errors.Cause in handler so that we return correct status codes 2018-05-17 16:30:48 -05:00
Travis Turner
12352e598f
increase cluster poll in tests from 2s to 10s 2018-05-17 15:55:11 -05:00
Cody Soyland
422d901e44 Close HTTP handler gracefully (Fixes #1018)
An earlier version of this patch (PR #1019) was erroneously removed during a merge.
2018-05-17 15:47:56 -05:00
Cody Soyland
9d2fca7f39
Merge pull request #1300 from codysoyland/enterprise-make-fix
Makefile enterprise build fixes
2018-05-17 14:25:40 -05:00
Cody Soyland
6d2d8080de Fix syntax for multiple build tags, add boolean flag for RELEASE, improve boolean handling to support "0" 2018-05-17 13:22:36 -05:00
Yuce Tekol
b69d7c67c0
Merge pull request #1296 from yuce/docker-cluster-tutorial
Added Docker cluster tutorial
2018-05-17 06:00:10 +03:00
Yuce Tekol
b4aa9013a4
Updated Docker cluster tutorial 2018-05-17 05:26:46 +03:00
Yuce Tekol
059810b99f
Docker cluster update 2018-05-17 05:12:28 +03:00
Travis Turner
e7e3e2def5
adjust cluster state tests so they aren't so dependent upon a sleep before checking state 2018-05-16 13:06:23 -05:00
Cody Soyland
f4baea7650
Merge pull request #1294 from codysoyland/make-enterprise-fix
Re-add unintentionally removed check-clean
2018-05-16 09:58:21 -05:00
Yuce Tekol
f3eed9de2a
docker cluster tutorial updates 2018-05-16 17:24:32 +03:00
Yuce Tekol
b40f257179
Added Docker cluster tutorial 2018-05-16 17:00:22 +03:00
Cody Soyland
bf789e2e97 Re-add unintentionally removed check-clean. Add ability to skip check-clean. 2018-05-16 08:47:36 -05:00
Cody Soyland
e7bd468562
Merge pull request #1292 from codysoyland/make-enterprise-fix
Fix syntax error and add i386 enterprise build
2018-05-16 07:50:44 -05:00
Cody Soyland
a2ef9afabb Fix syntax error and add i386 enterprise build 2018-05-15 17:09:45 -05:00
Cody Soyland
1ae4705140
Merge pull request #1291 from codysoyland/release-v0.10.0
Release v0.10.0
2018-05-15 16:55:09 -05:00
Cody Soyland
683c524c60 Release v0.10.0 2018-05-15 16:49:21 -05:00
alanbernstein
df32da1c8c
Merge pull request #1281 from alanbernstein/docs-intro-fixes
Assorted docs fixes
2018-05-15 16:34:28 -05:00
Cody Soyland
76fa64df79
Merge pull request #1285 from codysoyland/vendor-btree
B+Tree Containers / Enterprise
2018-05-15 16:32:15 -05:00
Matt Jaffee
4f3a4864f0
add godoc comment to enterprise/enterprise.go 2018-05-15 16:08:54 -05:00
Travis Turner
c27faaa271
add GOARCH=386 ENTERPRISE=1 to travisCI 2018-05-15 16:07:58 -05:00
Matt Jaffee
61fcf99f3e
unexport bitmapsEqual 2018-05-15 15:53:26 -05:00
Matt Jaffee
00a39aa338
implement Container.equals and get rid of reflect 2018-05-15 15:18:44 -05:00
Travis Turner
f9aa854918
add Licenses section to readme 2018-05-15 15:02:22 -05:00
Alan Bernstein
b77462e8ad Improve FAQ 2018-05-15 14:44:27 -05:00
Alan Bernstein
53dc34c36e Fix some docs links 2018-05-15 14:36:02 -05:00
Alan Bernstein
537c0e160a Address review comments 2018-05-15 14:35:35 -05:00
Matthew Jaffee
d2853cda56
Merge pull request #1286 from jaffee/remove-unused-code
Remove unused code
2018-05-15 13:48:19 -05:00
Travis Turner
b363debd83
replace "Pilosa starting..." log line 2018-05-15 12:52:49 -05:00
Cody Soyland
b1eb137a20 Add missing license headers. 2018-05-15 12:26:33 -05:00
Cody Soyland
1f925324d7 Add enterprise license 2018-05-15 12:20:45 -05:00
Cody Soyland
5103bfd8ce Remove errant "z". 2018-05-15 11:34:47 -05:00
Cody Soyland
cfb9146515 Use NewFileBitmap to get container implementation for testing ContainersIterator. 2018-05-15 11:30:37 -05:00
Cody Soyland
e8fcb0f055 Use NewFileBitmap for tests to test btree/slice containers separately. 2018-05-15 11:22:19 -05:00
Matt Jaffee
8ae170ac6c
simplify regexes by using backquoted strings to avoid double escapes 2018-05-15 11:05:36 -05:00
Matt Jaffee
c543831937
remove unused code
nodeByURI, deleteFrameFieldRequest, readColumnAttrSets, validOptions, defaultBody
2018-05-15 11:05:31 -05:00
Matt Jaffee
620226d6ef
simplify comparisons to bool constants 2018-05-15 11:00:09 -05:00
Matt Jaffee
a0f4c613a2
remove uneccessary underscores when accessing map values 2018-05-15 10:58:33 -05:00
Cody Soyland
36aab7e223 Use new enterprise flag 2018-05-15 10:56:57 -05:00
Matt Jaffee
652b5695e1
fix redundant arguments to make() calls 2018-05-15 10:56:24 -05:00
Matt Jaffee
a3445ec884
simplify loops with append... in cluster.go 2018-05-15 10:48:40 -05:00
Matt Jaffee
68dec9c60a
remove unnecessary capacity in make() 2018-05-15 10:46:41 -05:00
Matt Jaffee
0e38eae6e3
convert time.Now().Sub() to time.Since() 2018-05-15 10:45:58 -05:00
Matt Jaffee
2b311d267c
check some unchecked errors 2018-05-15 10:42:55 -05:00
Cody Soyland
57e904f1fc Re-add Todd\'s benchmark functions lost during merge 2018-05-15 10:41:33 -05:00
Cody Soyland
89f3c10d2c Clarify comment 2018-05-15 10:25:53 -05:00
Cody Soyland
71373945da Rename Contiterator -> ContainerIterator 2018-05-15 10:22:02 -05:00
Cody Soyland
1c715aebe7 Improve enterprise build process 2018-05-15 10:16:55 -05:00
Matt Jaffee
1550279ebc
simplify some error returns
removes unnecessary if statements
2018-05-14 19:29:29 -05:00
Matt Jaffee
0c06549a5b
remove unnecessary returns in stats_test.go 2018-05-14 19:29:29 -05:00
Matt Jaffee
a10750009b
remove decodeColumnAttrSet(s) (unused) 2018-05-14 19:29:29 -05:00
Matt Jaffee
b280ab2c47
remove MustParseTimePtr 2018-05-14 19:29:29 -05:00
Matt Jaffee
eb5187bfd0
remove encode/decodeURIs 2018-05-14 19:29:29 -05:00
Matt Jaffee
fb8cc455b6
remove viewSlice (unused) 2018-05-14 19:29:28 -05:00
Matthew Jaffee
c55209a9fb
Merge pull request #1284 from jaffee/remove-input-def
remove input definition, add install-stringer to Makefile
2018-05-14 18:49:24 -05:00
Alan Bernstein
3bb140a45c Remove TODO 2018-05-14 18:18:39 -05:00
Alan Bernstein
e8ce4b99d6 Clarify PDK schema table 2018-05-14 18:18:09 -05:00
Alan Bernstein
6cc848efc9 Update sample CLI output 2018-05-14 18:17:04 -05:00
Alan Bernstein
d0ae47f350 Minor corrections 2018-05-14 18:16:29 -05:00
Alan Bernstein
c8ff67262d Add some links 2018-05-14 18:15:37 -05:00
Cody Soyland
208dc1c8dc Add new things to PHONY 2018-05-14 17:54:11 -05:00
Alan Bernstein
6e1ddf7400 Minor grammar and formatting fixes 2018-05-14 17:54:02 -05:00
Cody Soyland
251d21dee1 Remove leftover debug log line 2018-05-14 17:51:10 -05:00
Alan Bernstein
b670afaa8d Clean up CLI 2018-05-14 17:46:11 -05:00
Cody Soyland
b4b28cb8bd Add enterprise tests to CI and Makefile 2018-05-14 17:38:39 -05:00
Cody Soyland
513c7fd705 B+tree integration work.
Export necessary vars from roaring to fix b+tree containers implementation.
Clean up naming.
Use constructor replacement for enterprise integration.
2018-05-14 17:32:30 -05:00
Matt Jaffee
616545cd5c
remove input definition, add install-stringer to Makefile
also removes one line of unreachable code in cluster.go (unrelated)
2018-05-14 17:14:20 -05:00
Cody Soyland
4282e90fe1 Export a few things to enable enterprise/b/containers_btree.go to work 2018-05-14 14:03:46 -05:00
Alan Bernstein
f053d9a541 Fix formatting 2018-05-14 12:27:33 -05:00
Alan Bernstein
2c125b2ac3 Fix typos 2018-05-14 12:07:00 -05:00
Alan Bernstein
0504172cc5 Expand TopN query examples 2018-05-14 11:47:10 -05:00
Alan Bernstein
540ba2b804 Add example output in Java client section 2018-05-14 11:19:21 -05:00
Alan Bernstein
4fcf5ef1ca Address review comments 2018-05-14 11:18:54 -05:00
Cody Soyland
faa79a385c Add B+tree to enterprise subpackage 2018-05-11 20:20:24 -05:00
Alan Bernstein
f0a4e5ab82 Fix broken github tree link 2018-05-11 15:56:20 -05:00
Alan Bernstein
d90e4f2745 Add request+response language tags, and update interleaved query-language wording 2018-05-11 14:55:15 -05:00
Alan Bernstein
bdc00a4212 Add a few links 2018-05-11 14:52:59 -05:00
Alan Bernstein
2abca951e7 Minor formatting fixes 2018-05-11 14:52:35 -05:00
Alan Bernstein
22cb90c1a3 Update relational analogy section 2018-05-11 14:51:42 -05:00
Alan Bernstein
d9affeea73 Miscellaneous wording and grammar updates 2018-05-11 14:50:41 -05:00
Alan Bernstein
8339e913ce Fix pql syntax in getting-started 2018-05-11 14:44:32 -05:00
Alan Bernstein
a7459a9450 Fix typo 2018-05-11 14:42:55 -05:00
Alan Bernstein
fedf8c44bf Minor updates to contributing guide and docs readme 2018-05-11 14:42:29 -05:00
Alan Bernstein
36d2bfd4ce Add sample output to client examples 2018-05-11 14:41:26 -05:00
Alan Bernstein
09302050ec Fix syntax in go client example 2018-05-11 14:41:04 -05:00
alanbernstein
d36e33fa52
Merge pull request #1279 from alanbernstein/bench-columnid-fix
Update PQL syntax in bench subcommand
2018-05-11 11:12:28 -05:00
Cody Soyland
4014f22802 Rename (export) container -> Container 2018-05-11 10:57:06 -05:00
Cody Soyland
bfb692e37e
Merge pull request #1278 from codysoyland/webui-help-menu-fixes
Update help menu in WebUI. Fixes #1277.
2018-05-11 10:44:40 -05:00
Alan Bernstein
a1ad7de82c Update PQL syntax in bench subcommand 2018-05-11 10:41:54 -05:00
Yuce Tekol
ec10e74c85
Merge pull request #1239 from yuce/1090-testdata-for-fragment-benchmarks
[TRIVIAL] Adds fragment test data, implements #1090
2018-05-11 17:48:07 +03:00
Yuce Tekol
2dcd664a28
Added a comment about how to create the sample fragment file 2018-05-11 17:17:15 +03:00
Yuce Tekol
beef74a31e
Merge pull request #1238 from yuce/1235-remove-endpoints
Removes /id and /hosts endpoints. Adds local ID to /status
2018-05-11 16:57:29 +03:00
Yuce Tekol
90464dc01a
Merged with master 2018-05-11 16:41:36 +03:00
Cody Soyland
e24d2648c0 Update help menu in WebUI. Fixes #1277. 2018-05-11 08:36:10 -05:00
Alan Bernstein
7783716f37 Add relational analogy section 2018-05-10 22:30:27 -05:00
alanbernstein
cc39733bf5
Merge pull request #1271 from alanbernstein/wrap-errors-index
Wrap errors index
2018-05-10 19:13:17 -05:00
alanbernstein
64ebae3a8a
Merge branch 'master' into wrap-errors-index 2018-05-10 18:57:44 -05:00
alanbernstein
64d55d502a
Merge pull request #1258 from alanbernstein/wrap-errors-frame
Wrap errors in frame
2018-05-10 18:45:47 -05:00
Alan Bernstein
bbdb2d207c Fix typo 2018-05-10 18:22:48 -05:00
alanbernstein
515b1bd418
Merge branch 'master' into wrap-errors-frame 2018-05-10 17:54:05 -05:00
alanbernstein
32ed40ad45
Merge pull request #1274 from alanbernstein/wrap-errors-fragment
Wrap errors in fragment
2018-05-10 17:48:08 -05:00
alanbernstein
d5cf49eca0
Merge pull request #1270 from alanbernstein/wrap-errors-api
Wrap errors in api
2018-05-10 17:47:52 -05:00
alanbernstein
ec503740e4
Merge branch 'master' into wrap-errors-frame 2018-05-10 17:28:54 -05:00
alanbernstein
449f3774b4
Merge branch 'master' into wrap-errors-api 2018-05-10 17:25:44 -05:00
Alan Bernstein
01b56b9c09 Fix return type typo 2018-05-10 17:17:45 -05:00
Alan Bernstein
a229b0f30d Make error string more specific 2018-05-10 16:02:40 -05:00
Alan Bernstein
8c5f2bd76b Address review comments 2018-05-10 13:56:52 -05:00
alanbernstein
692388c511
Merge pull request #1273 from alanbernstein/wrap-errors-attrstore
Wrap errors in attrstore
2018-05-10 13:11:15 -05:00
alanbernstein
a3438ba6e2
Merge pull request #1272 from alanbernstein/wrap-errors-leftovers
Wrap remaining errors in a few more files
2018-05-10 13:10:24 -05:00
Alan Bernstein
6e28624528 Wrap errors in fragment 2018-05-10 13:09:07 -05:00
Alan Bernstein
eb888b74f7 Update test error strings 2018-05-10 12:12:55 -05:00
Alan Bernstein
0ba14600da Wrap a few more errors 2018-05-10 12:08:46 -05:00
Alan Bernstein
a172720531 Update error check string 2018-05-10 11:59:40 -05:00
Alan Bernstein
4f300f5c2e Wrap errors in index 2018-05-10 11:33:14 -05:00
Cody Soyland
2590b25628 Merge branch 'master' into vendor-btree 2018-05-10 11:28:13 -05:00
alanbernstein
3dfaa037ac
Merge pull request #1260 from alanbernstein/wrap-errors-handler
Wrap errors in handler
2018-05-10 11:26:45 -05:00
Alan Bernstein
7a38c98901 Wrap errors in api 2018-05-10 11:24:51 -05:00
alanbernstein
a2b7ef2ad9
Merge pull request #1259 from alanbernstein/wrap-errors-view
Wrap errors in view
2018-05-10 11:10:39 -05:00
Alan Bernstein
17520033c6 Update test error strings 2018-05-10 10:57:27 -05:00
alanbernstein
762b5550c9
Merge pull request #1256 from alanbernstein/wrap-errors-executor
Wrap errors in executor
2018-05-10 10:38:46 -05:00
alanbernstein
1e9252c1bb
Merge pull request #1257 from alanbernstein/wrap-errors-cluster
Wrap errors in cluster.go
2018-05-10 10:38:35 -05:00
alanbernstein
dbeff51cf8
Merge pull request #1261 from alanbernstein/wrap-errors-holder
Wrap errors in holder
2018-05-10 10:29:14 -05:00
alanbernstein
13f70c36c8
Merge pull request #1262 from alanbernstein/wrap-errors-ctl
Wrap errors in ctl/*.go
2018-05-10 10:28:05 -05:00
alanbernstein
648dedacf7
Merge pull request #1263 from alanbernstein/wrap-errors-server
Wrap errors in server/
2018-05-10 10:27:02 -05:00
alanbernstein
6b493cca8d
Merge pull request #1265 from alanbernstein/wrap-errors-client
Wrap errors in client.go
2018-05-10 10:26:48 -05:00
tgruben
aa37f50f42
Merge pull request #1268 from tgruben/dead-lock-fix
Dead lock fix
2018-05-10 09:06:02 -05:00
Travis Turner
1fb5a5efe8
Merge pull request #1266 from travisturner/gossip-logger
make sure gossipMemberSet.Logger is set during server setup
2018-05-09 23:17:53 -05:00
Travis Turner
af51ef9c18
Merge pull request #1269 from wiggzz/master
Correct usage of ClearBit in docs
2018-05-09 22:02:46 -05:00
Will James
9710ac978d
Correct usage of ClearBit
Usage of `ClearBit` was incorrectly shown as `SetBit`.
2018-05-09 21:30:49 -04:00
Alan Bernstein
57261bda9f Fix spelling error 2018-05-09 15:52:02 -05:00
Todd Gruben
a436d4d32a fixed deadlock in setcooridnator 2018-05-09 15:00:39 -05:00
Travis Turner
59291e2936
Merge pull request #1255 from travisturner/minor-api-tweak
API.URI was not being used. removed it.
2018-05-09 11:17:49 -05:00
Alan Bernstein
4f6947af3b Update error messages 2018-05-09 10:50:17 -05:00
Travis Turner
5e043919ae
default GossipMemberSet.Logger to NopLogger 2018-05-09 10:48:49 -05:00
Alan Bernstein
b74e5e7ec7 Update error message 2018-05-09 10:46:16 -05:00
Travis Turner
e4c11a28b1
make sure gossipMemberSet.Logger is set during server setup 2018-05-09 10:42:11 -05:00
Travis Turner
43ec69d08b
API.URI was not being used. removed it. 2018-05-09 09:32:18 -05:00
Yuce Tekol
24c9699432
Merge pull request #1242 from yuce/dont-create-tilde-directory-when-running-tests
Make sure ~ is expanded in NewServer; BroadcastReceiver uses temp path
2018-05-09 09:53:02 +03:00
Alan Bernstein
248d9b4ffb Wrap errors in view 2018-05-08 19:53:05 -05:00
Alan Bernstein
a3dc756be4 Wrap errors in handler 2018-05-08 19:46:26 -05:00
Alan Bernstein
4f51373734 Wrap errors in holder 2018-05-08 19:43:36 -05:00
Alan Bernstein
3907e21f6f Wrap errors in frame 2018-05-08 18:40:44 -05:00
Alan Bernstein
4452cd7260 Wrap errors in cluster.go 2018-05-08 18:29:04 -05:00
Alan Bernstein
f839118121 Wrap errors in executor 2018-05-08 18:17:22 -05:00
Alan Bernstein
68924fe0ad Wrap errors in client.go 2018-05-08 17:40:15 -05:00
Yuce Tekol
0244f4b51d
Added dataDir field to Server 2018-05-09 01:27:42 +03:00
Alan Bernstein
f0b6fa4ee8 Wrap errors in server/ 2018-05-08 17:20:06 -05:00
Alan Bernstein
f5a4fd82b1 Wrap errors in ctl/*.go 2018-05-08 17:10:36 -05:00
Todd Gruben
e50b2aee24 Merge remote-tracking branch 'upstream/master' 2018-05-08 09:35:58 -05:00
Yuce Tekol
96620dd2df
Merge pull request #1236 from yuce/1232-server-info
Added /info endpoint. Fixes #1232
2018-05-08 03:02:48 +03:00
Travis Turner
cea4b02941
Merge pull request #1234 from travisturner/nil-timestamp-slice
avoid creating a slice of nil timestamps on Import()
2018-05-07 16:17:12 -05:00
Matthew Jaffee
134a88d91d
Merge pull request #1253 from jaffee/fixup-internal-client
Fixup internal client
2018-05-07 12:43:12 -07:00
Matt Jaffee
b2eb8f02ee
fix QueryNode comment 2018-05-07 12:42:39 -07:00
Matt Jaffee
420631e748
remove last vestiges of passing URI via context
this chould be safe as context.WithValue doesn't seem to appear anywhere else in Pilosa
2018-05-07 12:40:38 -07:00
Matt Jaffee
2738c92286
stop passing uri via context to InternalClient.ExecuteQuery 2018-05-07 12:40:38 -07:00
Matt Jaffee
0d3df71e37
add URI argument to InternalClient.SendMessage
passing values through context is error prone and usually bad practice.
2018-05-07 12:40:37 -07:00
Matt Jaffee
b3f529cb1b
remove unused NodeID method on InternalClient 2018-05-07 12:40:35 -07:00
Todd Gruben
2c9d238acf Merge remote-tracking branch 'upstream/master' 2018-05-07 09:22:30 -05:00
Cody Soyland
bba472f012
Merge pull request #1251 from codysoyland/release-v0.9.0
Release v0.9.0
2018-05-04 17:38:05 -05:00
Cody Soyland
7cecfd30cf Changelog fixes 2018-05-04 17:07:39 -05:00
Cody Soyland
76ee46bd0d Add note about upgrading to v0.9 2018-05-04 17:03:43 -05:00
Cody Soyland
4454bedb3d Update changelog 2018-05-04 16:28:19 -05:00
Cody Soyland
3529043fbc Update Go version 2018-05-04 16:22:08 -05:00
Cody Soyland
995a90ac9d Update pilosa version in installation docs 2018-05-04 16:22:00 -05:00
Cody Soyland
46a929e1d6 More updates for v0.9 branch 2018-05-04 15:49:03 -05:00
Cody Soyland
84ed1953bd Update changelog 2018-05-04 15:40:56 -05:00
Matthew Jaffee
eec784f0dd
Merge pull request #1228 from pilosa/cluster-race-conds
Cluster race conds
2018-05-04 11:39:47 -07:00
Matthew Jaffee
985b56f50b fix utils_test comments 2018-05-04 10:48:57 -07:00
Todd Gruben
4a1d15ec9d missed a file on last commit 2018-05-04 10:48:57 -07:00
Todd Gruben
2ef78af0ca adjusted protection around cluster coordinator mutations 2018-05-04 10:48:57 -07:00
Matthew Jaffee
992c3e8bdd WIP - adding more locking to Cluster 2018-05-04 10:48:57 -07:00
Cody Soyland
3c48efb5b5
Merge pull request #1246 from codysoyland/391-log-startup
Log time/version to startup log (Fixes #391)
2018-05-04 12:48:15 -05:00
Cody Soyland
fab755573b
Merge pull request #1245 from codysoyland/id-file-name
Rename ID file to ".id" for consistency with existing data files
2018-05-04 12:47:47 -05:00
Cody Soyland
9e1a7d45a6
Merge pull request #1250 from codysoyland/upgrading-docs
Add docs for upgrading Pilosa
2018-05-04 12:47:23 -05:00
Cody Soyland
0afb95c171 Minor upgrading docs changes 2018-05-04 12:33:20 -05:00
Cody Soyland
e751945bf1 Add docs for upgrading Pilosa 2018-05-04 11:33:59 -05:00
Cody Soyland
85f90ac8fc Log time/version to startup log (Fixes #391) 2018-05-03 16:11:43 -05:00
Yuce Tekol
beaa69a7bd
Made expandDirName generic. 2018-05-03 00:07:56 +03:00
Cody Soyland
18d7664fc4 Rename ID file to ".id" for consistency with existing data files. 2018-05-02 15:04:12 -05:00
Travis Turner
b961378b2f
Merge pull request #1221 from travisturner/vendor-lrucache
vendor github.com/golang/groupcache/lru. rebuild Gopkg.lock
2018-05-02 12:58:55 -05:00
Travis Turner
331a4fc5b8
add NOTICE to binary distributions 2018-05-02 12:21:03 -05:00
Yuce Tekol
244c4e894e
Remove ~ expanding code from Command.Start 2018-05-02 17:33:51 +03:00
Yuce Tekol
806437bd23
Make sure ~ is expanded in NewServer; BroadcastReceiver uses temp path 2018-05-02 17:07:17 +03:00
Yuce Tekol
b34e87a094
Typo 2018-05-01 17:31:01 +03:00
Yuce Tekol
02b67ed101
Adds fragment test data, implements #1090 2018-05-01 17:28:10 +03:00
Travis Turner
437fcc5438
Merge pull request #1237 from willf/fix-misssspelllingz
fix minor spelling errors
2018-05-01 09:20:45 -05:00
Yuce Tekol
878b55ec40
Removes /id and /hosts endpoints. Augments /status endpoint with the node local ID. 2018-05-01 13:04:49 +03:00
Will Fitzgerald
5a56b33826 fix minor spelling errors 2018-05-01 05:45:19 -04:00
Yuce Tekol
15f997c137
Added /info endpoint. Fixes #1232 2018-04-30 16:45:31 +03:00
Travis Turner
7f41c0256c
avoid creating a slice of nil timestamps on Import() 2018-04-29 16:40:32 -05:00
Matthew Jaffee
fdd552bf30
Merge pull request #1233 from jaffee/nil-client-bug
fix nil client bug in monitorAntiEntropy (and test)
2018-04-28 09:55:45 -05:00
Matthew Jaffee
57ac2f40aa
fix nil client bug in monitorAntiEntropy (and test)
also fix bug where broadcast_test tried to listen on localhost:10101
2018-04-28 09:12:59 -05:00
Cody Soyland
94f4015196
Merge pull request #1230 from codysoyland/build-matrix-goarch
Use build matrix instead of separate commands to test different architectures
2018-04-27 14:58:49 -05:00
Cody Soyland
52002f5455 Correct travis.ci matrix build config 2018-04-27 14:51:54 -05:00
Cody Soyland
0f8b630ab2 Only run "deployment" (binary prerelease upload) for one build condition. 2018-04-27 11:43:31 -05:00
Cody Soyland
210c78a20a Use build matrix instead of separate commands to test different architectures 2018-04-27 11:26:05 -05:00
Yuce Tekol
64953b4cd5
Merge pull request #1229 from yuce/fix-crash
[URGENT] Fixes crash due to server.diagnostics.server not set
2018-04-27 15:20:23 +03:00
Yuce Tekol
75bd93d895
Fixes crash due to server.diagnostics.server not set 2018-04-27 15:11:15 +03:00
Matthew Jaffee
dbc4e150e2
Merge pull request #1226 from jaffee/server-refactoring
remove holder.Peek, combine with HasData, move server logic
2018-04-24 20:21:53 -05:00
Travis Turner
47607d5d2e
Merge pull request #1191 from travisturner/min-max-bsi
Implement Min/Max BSI queries
2018-04-24 11:00:35 -05:00
Matthew Jaffee
abda2a1267
Merge pull request #1213 from jaffee/1204-pdk-docs
remove outdated pdk docs, and write some new ones
2018-04-24 09:24:35 -05:00
Matthew Jaffee
a15dde5291
Merge branch 'master' into 1204-pdk-docs 2018-04-24 08:57:31 -05:00
Yuce Tekol
6285a8cf0f
Merge pull request #1225 from yuce/test-32bits
Run 32bits on CI
2018-04-24 16:55:40 +03:00
Matthew Jaffee
f9ff20689a
remove holder.Peek, combine with HasData, move server logic
Server initializing happens more in NewServer than Open now - expecting to
continue this trend. goal was to remove remoteClient from Server (since it has a
defaultClient) as well, but we'll have to refactor the client usage in fragment
and frame first.
2018-04-24 08:44:58 -05:00
Yuce Tekol
ff8ab6930a
Run 32bits on CI 2018-04-24 16:13:36 +03:00
Travis Turner
7fbd5ff82f
Merge pull request #1222 from travisturner/remove-frame-timequantum-patch
remove PATCH frame endpoint
2018-04-23 20:32:12 -05:00
Travis Turner
579234d216
Merge pull request #1224 from travisturner/docs-row-col
remove references to row and column labels from the docs
2018-04-23 18:56:00 -05:00
Matthew Jaffee
87702af9a4
Merge pull request #1220 from jaffee/refactor-logger
refactoring pilosa/server
2018-04-23 17:32:39 -05:00
Travis Turner
7ecd2ec794
adjust references to RowID and ColumnID in the docs 2018-04-23 17:10:48 -05:00
Travis Turner
e4a7e2edbd
remove references to row and column labels from the docs 2018-04-23 16:47:22 -05:00
Matthew Jaffee
f99479932d
rename server Run to Start to better reflect functionality 2018-04-23 16:28:24 -05:00
Matthew Jaffee
9deefbaefc
unexport setupLogger and simplify 2018-04-23 16:25:03 -05:00
Matthew Jaffee
1e05a6d627
fix getListener comment 2018-04-23 15:15:02 -05:00
Matthew Jaffee
9f1720f01d
unexport stuff in pilosa.Server
refactor gossip.NewGossipMemberset to not take Server
2018-04-23 15:12:23 -05:00
alanbernstein
c1252f067c
Merge pull request #1215 from alanbernstein/deprecate-inverse-frames
Remove docs references to inverse frames
2018-04-23 14:46:07 -05:00
Travis Turner
c19950b239
Merge pull request #1223 from travisturner/container-flip
clean up flipBitmap and add tests
2018-04-23 14:32:01 -05:00
Matthew Jaffee
28acc29a10
refactoring pilosa/server
trying to separate internal an external concerns in pilosa.Server - it should
handle Cluster, Holder, etc. while pilosa/server handles things with external
deps - e.g. Logger, Stats, Handler, etc. Using functional options in
pilosa.Server now.
2018-04-23 13:35:39 -05:00
Travis Turner
23f5c7166b
cleat up flipBitmap and add tests 2018-04-23 13:23:35 -05:00
Travis Turner
3282cf8cbe
remove PATCH frame endpoint 2018-04-23 11:32:41 -05:00
Travis Turner
f2729b90d7
vendor github.com/golang/groupcache/lru. rebuild Gopkg.lock 2018-04-23 10:43:06 -05:00
Travis Turner
3a17b30e7d
Merge pull request #1219 from travisturner/remove-dead-code
remove Index.MergeSchemas() method
2018-04-23 08:24:35 -05:00
Travis Turner
edee152a9b
remove Index.MergeSchemas() method 2018-04-20 13:20:56 -05:00
Travis Turner
5177b243f3
use ValCount return type (instead of SumCount, MinCount, and MaxCount) 2018-04-19 17:03:49 -05:00
Matthew Jaffee
b53db06a6e
Merge pull request #1216 from jaffee/move-config-obj
move pilosa.Config to pilosa/server.Config
2018-04-19 16:05:08 -05:00
Matthew Jaffee
23f6acc165
panic if NewCommand errors on NewServer 2018-04-19 15:37:08 -05:00
Matthew Jaffee
876ed56e30
move pilosa.Config to pilosa/server.Config
step 1 of #1203

The Config object is really just a specification of the options to pilosa
server, so it makes sense to have it in that package.
2018-04-19 14:51:42 -05:00
Alan Bernstein
84e6493d7a Add deprecation warning to examples doc 2018-04-19 10:31:01 -05:00
Alan Bernstein
72eb3d239a Remove references to inverse frames 2018-04-18 14:18:57 -05:00
Travis Turner
5a740eb1d9
Merge pull request #1212 from travisturner/remove-input-defintion-docs
remove references to Input Defintion from the docs
2018-04-18 11:23:54 -05:00
Matthew Jaffee
ff8fea804c
remove outdated pdk docs, and write some new ones
incomplete, but an improvement?
2018-04-18 11:22:59 -05:00
Travis Turner
8c2387b45e
remove references to Input Defintion from the docs 2018-04-18 11:06:53 -05:00
Travis Turner
7f71b1649c
Merge pull request #1209 from travisturner/remove-index-timequantum
Remove Index.TimeQuantum
2018-04-18 10:10:23 -05:00
Travis Turner
e7151eb2a8
Remove Index.TimeQuantum 2018-04-18 08:17:26 -05:00
Travis Turner
590b7c30ab
Merge pull request #1207 from travisturner/security-manager-to-api
Remove SecurityManager. Implement api restrictions in api package.
2018-04-18 07:30:28 -05:00
Travis Turner
e60d11a23e
change references from "function" to "method" 2018-04-17 17:07:41 -05:00
Matthew Jaffee
ede383f8eb
Merge pull request #1205 from jaffee/1194-deprecate-rangeenabled
deprecate RangeEnabled, but leave in API
2018-04-17 16:39:10 -05:00
Travis Turner
5468065213
improve apiFunc error handling. change slice to map in function validation. 2018-04-17 13:01:36 -05:00
Matthew Jaffee
e56b8717b5
add better inverseEnabled with field test 2018-04-17 09:00:57 -05:00
Matthew Jaffee
58492c7eab
remove period in CHANGELOG 2018-04-17 07:54:25 -05:00
Travis Turner
0a8d573fb3
WIP: Remove SecurityManager. Implement api restrictions in api package. 2018-04-16 17:12:28 -05:00
Matthew Jaffee
c7f2d0f675
update unreleased section of CHANGELOG with rangeEnabled deprecation 2018-04-16 16:16:14 -05:00
Matthew Jaffee
fe0ba6280f
deprecate RangeEnabled, but leave in API
the RangeEnabled option now has no effect, but it still exists in the API. A few
tests still use it to ensure this. This would only be considered a breaking
change if someone was relying on Pilosa to enforce the RangeEnabled: false
option to prevent fields being created in certain frames. This seems unlikely.
2018-04-16 16:08:04 -05:00
Matthew Jaffee
d34f3354bb
Merge pull request #1200 from jaffee/1170-global-defaults
remove global defaults from config.go
2018-04-15 17:59:21 -05:00
Matthew Jaffee
7233597f35
remove DefaultConfig global (only used once). Fix data-dir comment 2018-04-15 17:20:14 -05:00
Matthew Jaffee
de29ddbb25
Merge pull request #1198 from jaffee/writerto-fix
use io.WriterTo instead of custom
2018-04-13 12:46:46 -05:00
Matthew Jaffee
0c35094bfc
few more docs tweaks 2018-04-13 10:21:47 -05:00
Yuce Tekol
8fb4df96a4
Merge pull request #1189 from yuce/1187-index-required-for-fragment-nodes
[TRIVIAL] index param is required for /fragment/nodes
2018-04-13 04:28:31 +03:00
Matthew Jaffee
3f303d1098
remove global defaults from config.go
these were occaisionally referenced elsewhere in the codebase - in all but one
case, there were workarounds that are actually better I think.

In the one case there wasn't I created a single top level DefaultConfig object
which is instantiated with all the default values and can be referred to if
necessary.

There was a bug in fragment.go with the way MaxWritesPerRequest was treated if
it was 0. Elsewhere, 0 meant no limit, but here, it would have caused a division
by 0.

Changed the default metrics provider from "nop" to "none", although "nop" will
still work. Previously, any value other than "statsd" or "expvar" was treated as
"nop", but I've changed this behavior to return an error if an invalid string is
provided. I think this is better behavior, because in the case that someone
bothered to change the default, they were probably interested in actually
getting stats, and might be annoyed when it silently failed.
2018-04-12 19:52:48 -05:00
Yuce Tekol
3695a8e889
Updated with master 2018-04-13 03:50:26 +03:00
Yuce Tekol
cde6082869
Merge branch 'master' into 1187-index-required-for-fragment-nodes 2018-04-13 03:43:17 +03:00
Yuce Tekol
e6dbdcb836
Merge pull request #1188 from yuce/tutorial-update
Updated tutorials
2018-04-13 03:42:36 +03:00
Yuce Tekol
a04ae99fb3
updated cluster tutorial with feedback 2018-04-13 03:41:59 +03:00
Matthew Jaffee
8ec801a732
use io.WriterTo instead of custom 2018-04-12 16:37:49 -05:00
Travis Turner
47a5ed84bd
add executor min/max tests. fix related bugs. 2018-04-12 15:49:55 -05:00
Matthew Jaffee
4343214001
Merge pull request #1197 from jaffee/handler-api-refactoring
Handler api refactoring
2018-04-12 12:56:32 -05:00
Matthew Jaffee
04f5d5875c
api docs, rename funcs, refactor usage of internal
All exported funcs in api.go are now documented

Several poorly named methods of API and Cluster were renamed. Particularly, the
word Fragment was often changed to Slice in cases where it was really a slice
being specified and not a fragment.

several methods which received or returned internal data structures have been
refactored to be more opaque.

Deprecation logging was added to input definition methods.
2018-04-12 11:28:35 -05:00
Travis Turner
ee4dbbf328
min/max documentation 2018-04-11 15:39:41 -05:00
Travis Turner
16539bbab1
WIP: implement Min/Max BSI queries 2018-04-11 15:39:40 -05:00
Matthew Jaffee
9257029da5
simplify Status endpoint
had to update test which was relying on a fake ClusterStatus implementation. Now
the status endpoint uses information directly from Cluster.Nodes and
Cluster.state - which is what Server (the usual ClusterStatus impl) uses, so it
should make no difference for real clusters.
2018-04-11 14:25:02 -05:00
Matthew Jaffee
9daef2180c
rename a number of API methods 2018-04-11 13:49:51 -05:00
Travis Turner
ea2921c192
Merge pull request #1192 from travisturner/inverse-slice-on-remote
make sure that slices is treated as inverseSlices on inverse calls
2018-04-11 13:30:51 -05:00
Matthew Jaffee
feec5f07e1
add more doc comments to api 2018-04-11 13:30:35 -05:00
Travis Turner
0d27139c04
test the inverseSlice fix 2018-04-11 12:51:26 -05:00
Matthew Jaffee
07ca6d57ad
variety of cleanup in api and handler
don't export QueryValidationSpecRequired
add docs to some methods
simplify /debug/vars handling using expvar.Handler()
implement Version in API and simplify
2018-04-11 09:42:05 -05:00
Travis Turner
3d595e6966
make sure that slices is treated as inverseSlices on inverse calls 2018-04-11 08:25:43 -05:00
Matthew Jaffee
dd5b38f4ef
Merge pull request #1190 from jaffee/1151-http-refactor
1151 http refactor
2018-04-10 10:55:10 -05:00
Matthew Jaffee
401c9682b8
remove commented code and fix double-NewAPI 2018-04-10 09:40:28 -05:00
Matthew Jaffee
07610560df
Merge branch 'master' into 1151-http-refactor 2018-04-10 08:10:25 -05:00
Matthew Jaffee
96e953e6e0
rename var to be more descriptive 2018-04-09 16:42:50 -05:00
Matthew Jaffee
f8cb579187
get tests passing 2018-04-09 14:29:43 -05:00
Todd Gruben
645a64e193 merge 2018-04-06 10:29:30 -05:00
Yuce Tekol
6d3f079b7a
updated row/col labels in getting started 2018-04-06 17:34:46 +03:00
Yuce Tekol
cc521e5c91
index param is required for /fragment/nodes 2018-04-05 22:29:03 +03:00
Yuce Tekol
81cac4775f
fix cluster config link 2018-04-05 19:53:05 +03:00
Yuce Tekol
17468e7d90
Updated tutorials 2018-04-05 19:43:40 +03:00
Travis Turner
1764d5a9bf
Merge pull request #1180 from travisturner/remove-rowcol-labels
Remove rowcol labels
2018-04-03 22:37:59 -05:00
Matthew Jaffee
be4965d962
fixup logger, handler.FileSystem 2018-04-03 16:09:11 -07:00
Yuce Tekol
c36dd395e6
All tests pass 2018-04-03 15:20:33 -07:00
Yuce Tekol
8336784d57
More API updates; removed Cluster, Holder, etc from Handler 2018-04-03 15:01:36 -07:00
Yuce Tekol
72526f753c
Moved more of handler to API 2018-04-03 14:52:59 -07:00
Yuce Tekol
b702f70610
Moved more of handler to API 2018-04-03 14:34:40 -07:00
Yuce Tekol
2ebc1914be
More API functions 2018-04-03 14:34:39 -07:00
Yuce Tekol
6c3f3ac0f0
Added API struct; moved query logic to API 2018-04-03 13:41:15 -07:00
Cody Soyland
298047903a
Merge pull request #1186 from codysoyland/fix-prerelease
Fix syntax on conditional check for docker-build config
2018-04-03 11:33:45 -05:00
Cody Soyland
0bf5f089a0 Run prerelease on Go 1.10 2018-04-03 11:25:54 -05:00
Cody Soyland
4b0da099b5 Fix syntax on conditional check for docker-build config 2018-04-03 11:09:49 -05:00
Travis Turner
ce4fb3c4d3
remove references to rowLabel and columnLabel 2018-04-03 10:36:48 -05:00
Cody Soyland
ba7720b4dd
Merge pull request #1181 from codysoyland/1146-makefile-cleanup
Makefile cleanup
2018-04-03 08:44:37 -05:00
Cody Soyland
ba9c26e689 Code review fixes: Create build directory if it doesn't exist. Use better URL for protoc installation instructions. 2018-04-02 16:39:14 -05:00
Cody Soyland
7f0208defb
Merge pull request #1185 from codysoyland/cluster-resize-webui-fixes
WebUI fixes for compatibility with API changes
2018-04-02 14:59:11 -05:00
Travis Turner
e3cd03d902
move rowLabel and columnLabel constants to executor.go 2018-04-02 13:05:37 -05:00
Travis Turner
083b730536
Merge pull request #1178 from travisturner/logger
Clean up logger; make it honor --log-path flag.
2018-04-02 11:48:17 -05:00
Todd Gruben
58ca5cf13a merge 2018-04-02 09:43:35 -05:00
Travis Turner
fb3a2b8b03
Merge pull request #904 from pilosa/cluster-resize
WIP: Cluster Resize
2018-03-30 16:12:33 -05:00
Travis Turner
421aff999b
Merge branch 'master' into cluster-resize 2018-03-30 15:54:32 -05:00
Cody Soyland
14dd54cc73 WebUI fixes to accommodate API changes 2018-03-29 15:50:53 -05:00
Cody Soyland
d59d20d27b Redundant chmod 2018-03-29 10:34:34 -05:00
Cody Soyland
9bf70705a3 Add docs for "make install-build-deps" 2018-03-28 12:23:03 -05:00
Cody Soyland
743726331f Add make instructions for travis-ci build process and use Makefile in Docker build 2018-03-28 12:22:47 -05:00
Cody Soyland
e601d694c0 Document Makefile 2018-03-27 15:02:12 -05:00
Cody Soyland
96e2ef534f Clean up Makefile
Turn off the automatic installation of build-time dependencies, which was
confusing and inconsistent. Update PHONY list. Simplify git status
check. Remove PKGS as Go 1.9+ automatically ignores `vendor` when
running tests. Consolidate release/prerelease build code. Add comments.
2018-03-27 14:25:27 -05:00
Travis Turner
5c52e48b12
change NewStandardLogger() to only take an io.Writer 2018-03-27 10:30:41 -05:00
Travis Turner
36ce12da59
This commit adds a Close() method to the pilosa.Logger interface,
and it moves the file handling (open/close) out of the main Command and
into the interface implementation. The Logger implementations both have
a `Logger()` method which returns their internal logger (`*log.Logger`).
This is because the gossip setup (memberlist) needs a `*log.Logger` for
its configuration.
2018-03-27 08:40:05 -05:00
Travis Turner
fd8040e699
remove LogOutput and instead close any logger that implements io.Closer 2018-03-27 08:40:05 -05:00
Travis Turner
633d99b217
remove leftover logger from NopLogger implementation 2018-03-27 08:40:05 -05:00
Travis Turner
0dc8aa0a5c
add --verbose flag to docs 2018-03-27 08:40:05 -05:00
Travis Turner
d113ebe147
Support --verbose logging 2018-03-27 08:40:05 -05:00
Travis Turner
9a2aeac6f8
Clean up logger; make it honor --log-path flag.
Add functional options to NewGossipMemberSet.
2018-03-27 08:40:04 -05:00
Travis Turner
b2b0fd081a
Remove ColumnLabel support 2018-03-26 15:35:56 -05:00
Travis Turner
2a8172b2a3
Remove RowLabel support 2018-03-26 14:48:56 -05:00
Todd Gruben
b8b2b58804 add benchmark for import and snapshot 2018-03-26 10:59:48 -05:00
Travis Turner
5a95a49c83
Merge pull request #1179 from travisturner/remove-default-gossip-seed
Default gossip seed should be empty instead of local bind address
2018-03-26 10:21:02 -05:00
Cody Soyland
762196809d
Merge pull request #1175 from codysoyland/remove-unused-cgo
Remove unused cgo preamble
2018-03-26 09:40:08 -05:00
Cody Soyland
99eb00bbdc Remove obsolete coverage tools from Makefile
Go 1.10 allows -coverprofile when testing multiple packages, so these hacks are no longer needed.
2018-03-26 08:41:21 -05:00
Cody Soyland
80a06486d7
Merge pull request #1177 from codysoyland/cluster-resize-unreleased-changelog
Add unfinished release notes for v0.9
2018-03-23 19:02:06 -05:00
Cody Soyland
684e874396 Remove extra parentheses. 2018-03-23 19:01:16 -05:00
Cody Soyland
59bb134a52 Add unfinished release notes for v0.9 2018-03-23 19:01:16 -05:00
Travis Turner
7dd41399cb
Merge pull request #1169 from travisturner/attrstore-interface
put BoltDB behind AttrStore interface
2018-03-23 16:39:19 -05:00
Travis Turner
0ca7cfe498
Change Seeds() to GetBindAddr() to clarify GossipMemberSet testing. 2018-03-23 16:34:19 -05:00
Travis Turner
8686a8645c
Default gossip seed should be empty instead of local bind address 2018-03-23 15:11:45 -05:00
Cody Soyland
f9efa6c579 Use type func(string) AttrStore in place of interface AttrStoreGenerator for simplicity 2018-03-23 13:57:29 -05:00
Travis Turner
62cd22f017
Merge branch 'master' into cluster-resize 2018-03-22 16:05:20 -05:00
tgruben
4ffd28ca1b
Merge pull request #1167 from TocarIP/count
roaring: speed-up intersectionCountArrayBitmap
2018-03-22 15:01:45 -05:00
alanbernstein
78af37e2c6
Merge pull request #1164 from alanbernstein/docs-updates
Docs QA updates
2018-03-22 11:43:37 -05:00
Alan Bernstein
48081c1265 Move external tutorial list to a note under the main heading 2018-03-22 11:30:51 -05:00
Cody Soyland
4b96991a9d
Merge pull request #1176 from codysoyland/merge-changelog
Add CHANGELOG changes from v0.8 to master
2018-03-21 13:41:10 -05:00
Cody Soyland
cfd083042f Add CHANGELOG changes from v0.8 to master 2018-03-21 12:00:15 -05:00
Cody Soyland
a95993fb69 Remove unused cgo preamble 2018-03-20 17:17:40 -05:00
Alan Bernstein
daca793c7f Remove reference to deprecated index timeQuantum 2018-03-20 16:00:51 -05:00
Alan Bernstein
38812a38aa Improve links 2018-03-20 15:21:48 -05:00
Alan Bernstein
edb63e70b1 Synchronize mac and linux install sections 2018-03-20 15:17:48 -05:00
Alan Bernstein
96c7f285e5 Ensure directory exists before cloning 2018-03-20 14:52:15 -05:00
Alan Bernstein
23e65cc225 Clean up a few links 2018-03-20 14:45:27 -05:00
Alan Bernstein
9e5d011b4a Remove 'go get' in favor of 'git clone' or curlbash 2018-03-20 14:44:51 -05:00
Alan Bernstein
54cb6ce47e Add description for external tutorials 2018-03-20 14:21:16 -05:00
Alan Bernstein
0800c0348a Add readthedocs link 2018-03-20 12:48:46 -05:00
Alan Bernstein
ef4c709828 Deprecate input definitionn in docs 2018-03-20 12:47:22 -05:00
Alan Bernstein
457b1f394c Add format details to docs readme 2018-03-20 12:46:11 -05:00
Alan Bernstein
02a822bcd3 Merge README-dev.md into CONTRIBUTING.md 2018-03-20 12:44:39 -05:00
Travis Turner
7a0c7e581a
Merge pull request #1163 from travisturner/webui-interface
put Statik behind an interface
2018-03-20 08:42:36 -05:00
Travis Turner
1694dbe294
Merge pull request #1171 from travisturner/gossip-config-cleanup
remove the Gossip stutter from memberlist-related config options
2018-03-19 17:17:17 -05:00
Alan Bernstein
fa66de0461 Fix one more link 2018-03-19 16:13:54 -05:00
Travis Turner
241150ddeb
Merge pull request #1088 from travisturner/cluster-resize-docs
update docs to include cluster-resize config and instructions
2018-03-19 15:22:08 -05:00
Travis Turner
f3b140cfa4
update docs to consider coordinator as boolean 2018-03-19 14:52:53 -05:00
Alan Bernstein
bd76bfc25b Fix a few more internal links 2018-03-19 14:49:41 -05:00
Travis Turner
836c8f4c2f
remove the Gossip stutter from memberlist-related config options 2018-03-19 14:29:53 -05:00
Alan Bernstein
37015e32a5 Ensure internal links end with slash 2018-03-19 14:25:36 -05:00
Cody Soyland
68581d50c0 Remove empty line between godoc and package declaration 2018-03-19 14:04:21 -05:00
Cody Soyland
4e1ff7c86f Merge branch 'cluster-resize' into webui-interface 2018-03-19 14:02:01 -05:00
Cody Soyland
ce9100172b
Merge pull request #1168 from codysoyland/cluster-resize-license-text
Add license text headers
2018-03-19 13:45:07 -05:00
Travis Turner
b66bedd1ef
put BoltDB behind AttrStore interface 2018-03-19 11:30:41 -05:00
Cody Soyland
b36e8c7a14 Combine two subpackages and consolidate doc.go into filestystem.go for simplicity. 2018-03-19 08:39:17 -05:00
Cody Soyland
b424811da9 Add license text 2018-03-16 15:28:03 -05:00
Cody Soyland
3690264108 Change wording to reflect that you can specify more than one gossip seed 2018-03-15 16:25:06 -05:00
Travis Turner
f31966553f update docs to include cluster-resize config and instructions 2018-03-15 16:25:06 -05:00
Cody Soyland
70ec216acf
Merge pull request #1166 from codysoyland/cluster-resize-refactor-diagnostics
Refactor Diagnostics: Move to main package, remove gobreaker, add SystemInfo abstraction for gopsutil dependency injection
2018-03-15 15:52:03 -05:00
Cody Soyland
be70bbfed2 Fix bug: backend won't store empty strings. 2018-03-15 15:27:48 -05:00
Cody Soyland
85b33f1bfb Remove unused code and TODO and clarify with comment. 2018-03-15 15:27:01 -05:00
Cody Soyland
754de2e057 Add correct diagnostics interval to startup message. 2018-03-15 15:26:36 -05:00
Travis Turner
a9b72b5443
Merge pull request #1142 from travisturner/remove-old-gossip-config
remove old GossipPort and GossipSeed config options
2018-03-15 11:32:29 -05:00
Alan Bernstein
1452bf24d6 Clarify Sum description 2018-03-15 11:07:07 -05:00
Alan Bernstein
fae429f971 Remove outdated column labels 2018-03-15 10:57:19 -05:00
Cody Soyland
680acf4e3d Fix error on linux 2018-03-14 17:41:44 -05:00
Cody Soyland
2d425e32e9 Log platform 2018-03-14 17:33:54 -05:00
Cody Soyland
20dc1212f8 Address code review (mostly comments) 2018-03-14 16:51:40 -05:00
Cody Soyland
88471e94f1 Remove caching (the lib code is fast) and add tests 2018-03-14 16:50:27 -05:00
Alan Bernstein
00bbdc1107 Move SetFieldValue to write section 2018-03-13 14:50:09 -05:00
Cody Soyland
c2444870c6 Remove gobreaker dep and add HTTP timeout 2018-03-13 12:30:39 -05:00
Cody Soyland
f4c1e0c492 Refactor gopsutil into SystemInfo interface/subpackage for dependency injection. 2018-03-13 11:41:45 -05:00
Cody Soyland
510c64ef06 Move diagnostics into package pilosa 2018-03-12 16:32:35 -05:00
Travis Turner
1206e40931
Merge pull request #1158 from travisturner/cluster-resize-coordinator-bool
Cluster resize coordinator bool
2018-03-12 11:58:37 -05:00
Alan Bernstein
8cfe7583ce Fix broken anchor links 2018-03-09 15:27:21 -06:00
Alan Bernstein
1b4445a00d Fix formatting 2018-03-09 15:27:00 -06:00
Matthew Jaffee
17d1bd18aa
Merge pull request #1165 from dosko64/misspell
Fix misspells in comments
2018-03-09 10:03:51 -06:00
Ilias Dimos
13e3b04443 Fix misspells in comments 2018-03-09 14:12:15 +02:00
Alan Bernstein
85799739af Address review comments 2018-03-08 15:55:21 -06:00
Alan Bernstein
cb0ac00eb3 Switch ref links to relative urls 2018-03-08 14:31:03 -06:00
Travis Turner
2a462d5e42
make sure cluster.Nodes[].IsCoordinator values get updated. return old coordinator node in response. 2018-03-08 14:18:10 -06:00
Travis Turner
fa4e543e84
send a NodeJoin event on startup for cases where a quick restart has occurred and memberlist is not aware of it 2018-03-08 12:42:24 -06:00
Travis Turner
1cc45b22a2
Change Config.Coordinator from URI to bool 2018-03-08 12:42:24 -06:00
Cody Soyland
0a6f2d07f6 Move statik filesystem implemention to subpackage of statik package. 2018-03-08 08:38:29 -06:00
Alan Bernstein
f371e1c2f2 Add glossary terms 2018-03-07 18:11:39 -06:00
Alan Bernstein
a562e73fa4 Minor updates 2018-03-07 18:11:22 -06:00
Alan Bernstein
cf41e7c3f7 Alphabetize glossary 2018-03-07 16:17:05 -06:00
Alan Bernstein
2811ed7b09 Improve and linkify glossary 2018-03-07 16:15:45 -06:00
Alan Bernstein
64bf4827aa Minor fixes 2018-03-07 16:15:18 -06:00
Alan Bernstein
b59901b403 Linkify docs url 2018-03-07 16:13:25 -06:00
Cody Soyland
5a2e1c3703
Merge pull request #1162 from codysoyland/cluster-resize-remove-without-replicas
Proper error handling when attempting to remove node when there aren't enough replicas
2018-03-07 13:51:44 -06:00
Travis Turner
d6896ea0a5
rename StaticFileSystem to FileSystem. re-org statik files 2018-03-07 11:12:05 -06:00
Cody Soyland
42682e12a8 Address code review: Fix error handling and add comment 2018-03-07 09:45:27 -06:00
Alan Bernstein
04b17847ce Clean up glossary 2018-03-06 18:14:22 -06:00
Alan Bernstein
e7eb68b101 Add cosmosa to new external tutorials section 2018-03-06 17:48:40 -06:00
Alan Bernstein
2b1a3c8403 Add docs readme 2018-03-06 17:48:14 -06:00
Travis Turner
2d1464f037
Merge pull request #1159 from travisturner/cluster-resize-staticmemberset
Cluster resize staticmemberset
2018-03-06 17:18:01 -06:00
Travis Turner
ec07f69cad
Merge pull request #1160 from travisturner/cluster-resize-better-wording
add comments to exported methods. remove debugging test.
2018-03-06 17:17:29 -06:00
Travis Turner
e03dee9386
put Statik behind an interface 2018-03-06 17:02:08 -06:00
Cody Soyland
b7b92913d9 Add comment to listenForJoins 2018-03-06 15:13:24 -06:00
Cody Soyland
d28a30ebd4 Proper error handling when attempting to remove node when there aren't enough replicas 2018-03-06 15:11:46 -06:00
Travis Turner
d0009206b4
add comments to exported methods. remove debugging test. 2018-03-06 12:42:29 -06:00
Travis Turner
1233226aa0
remove Join method from StaticMemberSet struct 2018-03-06 12:18:44 -06:00
Travis Turner
36cc056618
Merge remote-tracking branch 'upstream/master' into cluster-resize 2018-03-06 12:14:38 -06:00
Matthew Jaffee
e34fcbf568
Merge pull request #1156 from jaffee/fix-container-comment
make container struct description more accurate
2018-03-04 15:06:47 -06:00
Matthew Jaffee
d04530a5c0
make container struct description more accurate 2018-03-03 11:45:48 -06:00
Matthew Jaffee
84e788dd3b
Merge pull request #1154 from jaffee/doc-seq-ids
add warnings about sequential ids
2018-03-02 12:00:19 -06:00
Matthew Jaffee
dcb411d028
add warnings about sequential ids 2018-03-02 11:00:46 -06:00
Ilya Tocar
2c8d9a5ae0 roaring: speed-up intersectionCountArrayBitmap
While looking at benchmarks as a possible go compiler benchmarks.
I've tried some optimizations by hand:
Move len(b.bitmap) load out of the loop.
Remove some type conversions.
Use (x >> off) & 1  to get offs bit, instead of  x & (1 << of)f >> off.

This produces nice speed-up and passes go test roaring.

name                                    old time/op  new time/op  delta
Bitmap_IntersectionCount_ArrayRun-6     2.06µs ± 0%  1.57µs ± 0%  -24.04%  (p=0.000 n=10+9)
Bitmap_IntersectionCount_BitmapRun-6    2.24µs ± 0%  2.24µs ± 0%     ~     (p=0.913 n=10+9)
Bitmap_IntersectionCount_ArrayBitmap-6  2.06µs ± 0%  1.56µs ± 1%  -24.05%  (p=0.000 n=9+10)
2018-02-28 17:08:26 -06:00
alanbernstein
280b21b533
Merge pull request #1135 from alanbernstein/docs-fixes
Docs fixes
2018-02-26 22:18:59 -06:00
Alan Bernstein
a20235f812 Add Xor spec 2018-02-26 15:26:28 -06:00
Travis Turner
97915cf5f9
Merge pull request #1148 from travisturner/gcnotify-interface
put GCNotify behind an interface
2018-02-26 10:51:00 -06:00
Travis Turner
10ebb6ab11
put GCNotify behind an inerface 2018-02-26 10:30:51 -06:00
Travis Turner
29dcfd06da
Merge pull request #1117 from travisturner/cluster-resize-handle-error
replace swallowed error with log entry
2018-02-23 16:37:42 -06:00
Matthew Jaffee
80fa535676
Merge pull request #1136 from jaffee/rem-col-label-docs
remove column label repo_id from query language docs
2018-02-23 14:21:04 -06:00
Travis Turner
c3f25e6d2c
Merge pull request #1143 from travisturner/scheme-in-bind-addr
handle the scheme correctly in config.Bind
2018-02-23 14:20:59 -06:00
Cody Soyland
66cc7a35c0
Merge pull request #1133 from codysoyland/redundant-gossip-seeds
Add support for lists of gossip seeds for redundancy
2018-02-23 12:03:16 -06:00
Cody Soyland
3bba35236f Add back example settings 2018-02-23 11:16:19 -06:00
Travis Turner
3d1538d53c
handle the scheme correctly in config.Bind 2018-02-23 10:48:55 -06:00
Travis Turner
1086c6c959
remove old GossipPort and GossipSeed config options 2018-02-23 10:22:32 -06:00
Yuce Tekol
c4fea5ecc7
Merge pull request #1140 from yuce/cluster-resize-handler-validation
Cluster resize handler validation
2018-02-23 18:35:49 +03:00
Cody Soyland
dbe917c9f4 Merge branch 'cluster-resize' into redundant-gossip-seeds 2018-02-23 09:20:28 -06:00
Yuce Tekol
82d2b31d52
Merged query arg validator 2018-02-23 15:21:05 +03:00
Travis Turner
359fc190bd
Merge pull request #1139 from travisturner/prevent-excessive-sendsync
prevent excessive sendSyce (createView) messages.
2018-02-22 16:55:07 -06:00
Travis Turner
2425a84a85
Merge pull request #1138 from travisturner/remove-node-validation
add validation around node-remove conditions
2018-02-22 16:53:48 -06:00
Travis Turner
e454473ec7
prevent excessive sendSyce (createView) messages. 2018-02-22 16:02:43 -06:00
Yuce Tekol
fcfc54eeeb
Merge pull request #1121 from yuce/652-validate-query-arguments
Validate /fragment/nodes arguments. Fixes #652
2018-02-22 23:01:34 +03:00
Cody Soyland
a23fe86839 Convert gossip seed string to slice 2018-02-22 13:14:45 -06:00
Travis Turner
52edeb72b4
add validation around node-remove conditions 2018-02-22 12:15:27 -06:00
Cody Soyland
fc6b0ea0e8 Add support for comma-separated list of gossip seeds for redundancy. 2018-02-22 11:45:50 -06:00
Yuce Tekol
25e244ebdf
Updates 2018-02-22 17:33:41 +03:00
Matthew Jaffee
a433a5ebfc
remove column label repo_id from query language docs
column labels are deprecated and the docs' usage of columnID vs repo_id was
inconsisent.
2018-02-21 16:42:35 -06:00
Travis Turner
c4f6a6beda
Merge branch 'master' into cluster-resize 2018-02-21 16:23:53 -06:00
Alan Bernstein
59d41a9cb3 Add Xor to docs 2018-02-21 15:42:46 -06:00
Alan Bernstein
73904db391 Fix indentation 2018-02-21 15:42:35 -06:00
Travis Turner
9c9a9382bf
Merge pull request #1132 from travisturner/broadcast-createfield
broadcast.SendSync field creation and deletion to all nodes
2018-02-21 15:23:43 -06:00
Travis Turner
da125e323c
broadcast.SendSync field creation and deletion to all nodes 2018-02-21 14:56:38 -06:00
Matthew Jaffee
f3e65e1b5a
Merge pull request #1130 from jaffee/remove-http-type-docs
remove cluster type http from docs
2018-02-21 14:49:31 -06:00
Matthew Jaffee
3e770a5eca
remove cluster type http from docs 2018-02-21 13:47:55 -06:00
Yuce Tekol
0417439afa
Validate all relevant endpoints; Changed how validation key is composed 2018-02-21 18:03:05 +03:00
Cody Soyland
cd2c6f0ae8
Merge pull request #1123 from codysoyland/go110
Go 1.10
2018-02-20 15:50:00 -06:00
Matthew Jaffee
cd5dd9bfd0
Merge pull request #1125 from jaffee/test-api-compat
add MustRunMainWithCluster test func to have api compatibility with c…
2018-02-20 12:06:55 -06:00
Matthew Jaffee
82592adf64
add MustRunMainWithCluster test func to have api compatibility with cluster resize
this will allow some pdk code which only works with cluster-resize to work
against master (i think)
2018-02-20 11:50:06 -06:00
tgruben
537df748ad
Merge pull request #797 from tgruben/gobits
Replace custom assembly bit functions with standard go
2018-02-20 10:05:38 -07:00
Todd Gruben
e01edb7e85 removed 1.8 from support; bits require 1.9 2018-02-20 10:42:42 -06:00
Todd Gruben
2d458b98a1 merge conflicts 2018-02-20 10:41:02 -06:00
Yuce Tekol
c1f9dd4e59
Added query arg validator middleware; updated Gorilla/mux 2018-02-20 15:38:58 +03:00
Cody Soyland
cf7faa2241 Use string instead of float for go 1.10 2018-02-19 10:48:02 -06:00
Cody Soyland
a8e1e93c34 Go 1.10 2018-02-19 10:34:47 -06:00
Yuce Tekol
8e6041d0fe
Validate /fragment/nodes arguments. Fixes #652 2018-02-19 13:55:19 +03:00
Travis Turner
7a840f5bf5
Merge pull request #1120 from travisturner/cluster-resize-merging
Cluster resize merging
2018-02-16 11:31:58 -06:00
Travis Turner
ea210cd525
remove extra context import 2018-02-16 11:21:47 -06:00
Travis Turner
6776fa81ef
Merge branch 'master' into cluster-resize-merging 2018-02-16 11:13:40 -06:00
Cody Soyland
15534daae7
Merge pull request #1119 from codysoyland/cluster-resize-fix-prerelease-upload
Cluster resize fix prerelease upload
2018-02-15 16:37:28 -06:00
Cody Soyland
f9c0c1548e Fix bug with prerelease upload 2018-02-15 16:32:08 -06:00
Cody Soyland
34e9824c1c
Merge pull request #1116 from codysoyland/cluster-resize-prerelease-builds
Make pre-release builds for all branches
2018-02-15 14:02:57 -06:00
Cody Soyland
b8d4f7233a Only deploy (prerelease upload) if using latest Go 2018-02-15 13:59:28 -06:00
Travis Turner
6374fedd7a
Merge pull request #1115 from travisturner/roaring-test-templates
Roaring test templates
2018-02-15 12:57:16 -06:00
Travis Turner
666fe22ecb
replace swallowed error with log entry 2018-02-15 12:11:27 -06:00
Cody Soyland
9558df2829 Make pre-release builds for all branches 2018-02-15 10:50:03 -06:00
Travis Turner
685a0075ae
add evenBits/oddBits container tests and related bug fix 2018-02-15 10:20:54 -06:00
Travis Turner
911af238ff
clean up roaring container helper functions 2018-02-14 15:06:53 -06:00
Travis Turner
673232baf9
bug fixes found by running container operation tests 2018-02-14 13:30:38 -06:00
Travis Turner
6529866b57
templates for testing various container operations 2018-02-14 13:30:07 -06:00
Travis Turner
5b95c04594
Merge pull request #1110 from travisturner/bitmapzerorange-bug
fixes a shift logic bug in bitmapZeroRange
2018-02-12 16:17:01 -06:00
Travis Turner
944a0b5b3d
fixes a shift logic bug in bitmapZeroRange that was causing an overflow-like condition 2018-02-12 15:23:00 -06:00
Yuce Tekol
72b2b77ea5
Merge pull request #1104 from yuce/1092-context-replacement
[TRIVIAL] 1092 context replacement
2018-02-12 22:00:43 +03:00
Yuce Tekol
8db3a9b64d
Merge pull request #1109 from yuce/1069-all-recalculate-caches
Spread recalculate caches to all nodes. Fixes #1069
2018-02-12 22:00:37 +03:00
Cody Soyland
b08d1ce3d3
Merge pull request #1102 from codysoyland/cluster-resize-validate-set-coordinator
Fix node id validation on set-coordinator
2018-02-12 11:25:30 -06:00
Cody Soyland
b9f4802729
Merge pull request #1100 from codysoyland/cluster-resize-webui
Re-add missing WebUI
2018-02-12 11:25:19 -06:00
Travis Turner
7f2e521579
Merge pull request #1091 from travisturner/metrics-docs
clarify the options in configuration for metrics.service
2018-02-12 09:16:16 -06:00
Yuce Tekol
657ff05e88
fix format strings which fail on go/master 2018-02-12 17:28:49 +03:00
Yuce Tekol
e2c2bd11e4
put back golang.org/x/net dep, required by golang.org/x/sync/errgroup 2018-02-12 17:16:38 +03:00
Yuce Tekol
c2d16f44e3
Spread recalculate caches to all nodes. Fixes #1069 2018-02-12 04:12:35 +03:00
Travis Turner
279906a03b
Merge pull request #1108 from travisturner/docs-request-response
add request/response tags to the docs
2018-02-09 17:25:55 -06:00
Travis Turner
db7e88f6d5
add request/response tags to the docs 2018-02-09 15:14:26 -06:00
Travis Turner
9e9a9f5ab3
Merge pull request #1105 from travisturner/fix-diffrunarray-overflow
avoid overflow bug in differenceRunArray
2018-02-09 11:57:11 -06:00
Travis Turner
ac4010bce0
avoid overflow bug in differenceRunArray which was appending a full run to the container 2018-02-09 11:35:13 -06:00
Yuce Tekol
a2580915ba
remove golang/org context from the lock 2018-02-09 17:34:18 +03:00
Yuce Tekol
f799d98564
Fixes #1092 2018-02-09 17:33:07 +03:00
Travis Turner
6fa742ee36
Merge pull request #1101 from travisturner/cluster-coordinator-fix
fix bug in NewServerCluster where each host was its own coordinator
2018-02-08 17:31:04 -06:00
Cody Soyland
b3532a617f Fix error message (panics since err == nil) 2018-02-08 16:50:44 -06:00
Travis Turner
1085be6582
fix bug in NewServerCluster where each host was its own coordinator 2018-02-08 15:11:51 -06:00
Cody Soyland
da2ab31945 Add generate-statik to CI job so WebUI test passes 2018-02-08 13:47:57 -06:00
Cody Soyland
ab1a1c7e82 Add test for WebUI 2018-02-08 13:25:14 -06:00
Cody Soyland
01c2ced8ae Add back missing WebUI handler 2018-02-08 13:09:00 -06:00
Travis Turner
6741a590ed
Merge pull request #1099 from travisturner/cluster-disabled
Changes configuration cluster.type (string) to cluster.disabled (bool)
2018-02-08 12:55:58 -06:00
Travis Turner
9085c03ce8
Changes configuration cluster.type (string) to cluster.disabled (bool) 2018-02-08 12:40:46 -06:00
tgruben
46ca04afab
Merge pull request #1081 from tgruben/hash-1049
Hash 1049
2018-02-08 11:44:37 -06:00
Travis Turner
34c3497e20
rebase and fix tests 2018-02-07 14:00:13 -06:00
Travis Turner
b301399dcd
remove skiplist container implementation 2018-02-07 13:56:59 -06:00
Matt Jaffee
26b6f6b119
rename NewBitmap to NewSliceBitmap 2018-02-07 13:56:58 -06:00
Cody Soyland
65dadd2b35
Copy verbatim vendored legal notice and modify binary distribution process to include legal notices 2018-02-07 13:56:58 -06:00
Travis Turner
be8b794060
add NOTICE for third-party software licenses; in this case: btree 2018-02-07 13:56:58 -06:00
Travis Turner
6c0acf4dd3
squash with vendor btree commit 2018-02-07 13:56:58 -06:00
Todd Gruben
23970b98dc
changed roaring.NewBitmapBTree to roaring.NewBTreeBitmap 2018-02-07 13:56:58 -06:00
Todd Gruben
440980384c
applied travis suggestions 2018-02-07 13:56:58 -06:00
Todd Gruben
36f59a0326
slice containers 2018-02-07 13:56:58 -06:00
Todd Gruben
8a70c4e5a3
added slice containers type for in memory bitmaps and btree for file based 2018-02-07 13:56:58 -06:00
Todd Gruben
a159c74498
corrected return value in updater to prevent allocation 2018-02-07 13:56:57 -06:00
Todd Gruben
f5d5cbb0b9
limited scope of closure in btree PutContainerValues 2018-02-07 13:56:57 -06:00
Todd Gruben
f825bc3b80
merge 2018-02-07 13:56:57 -06:00
Travis Turner
0757a84f69
add PutContainerValues to Containers interface to prevent re-allocation of containers 2018-02-07 13:56:57 -06:00
Travis Turner
0bed8de647
vendor btree in roaring package to test non-interface on key/value 2018-02-07 13:56:57 -06:00
Todd Gruben
3ae10fbd95
snapshot benchmarking 2018-02-07 13:56:57 -06:00
Travis Turner
e0fc49b512
reset lastContainer cache on Put to a mapped container. check lastContainer cache on Get 2018-02-07 13:56:57 -06:00
Travis Turner
ce052c133c
b+tree for Containers interface 2018-02-07 13:56:57 -06:00
Matthew Jaffee
fab493c42b
fix up missed conflict 2018-02-07 13:56:57 -06:00
Matthew Jaffee
5314d61086
Revert "remove interface"
This reverts commit 343e810bc65562d10d9408c941e65414c6945d9f.
2018-02-07 13:56:57 -06:00
Matthew Jaffee
be4696ebb9
remove interface 2018-02-07 13:56:56 -06:00
Matthew Jaffee
a42a1a2c37
make sure roaring.Bitmaps are created appropriately 2018-02-07 13:56:56 -06:00
Matthew Jaffee
d798963798
fix a bunch of bugs and add some tests 2018-02-07 13:56:56 -06:00
Matthew Jaffee
bc6fb2627f
add initial skip list Containers impl 2018-02-07 13:56:56 -06:00
Matthew Jaffee
cce3379abf
add Containers interface and modify Bitmap to use it
there are no implementations of Containers, so everything is broken, but the
code compiles
2018-02-07 13:56:56 -06:00
Travis Turner
5529040514
clarify the options in configuration for metrics.service 2018-02-07 11:29:58 -06:00
Matthew Jaffee
141fdd1db9
Merge pull request #1084 from jaffee/1082-onto-master
fix count/bitmap mismatch bug on master
2018-02-06 16:58:41 -06:00
Travis Turner
5a44d24c2f
Merge pull request #1080 from travisturner/ensure-license
ensure that the license header is included in all source files
2018-02-06 15:58:38 -06:00
Cody Soyland
e9bd1c7f0d Add license notice to two files 2018-02-06 14:15:37 -06:00
Travis Turner
1312ddf9a2
Merge branch 'master' into cluster-resize 2018-02-06 13:07:55 -06:00
Travis Turner
7db29aa1a7
Merge pull request #1087 from travisturner/fix-env-docs
fix description of ENV var configuration to include dot replacement
2018-02-06 13:00:01 -06:00
Travis Turner
19008d0ff0
fix description of ENV var configuration to include dot replacement 2018-02-06 12:22:51 -06:00
Travis Turner
29091b54bc
Merge branch 'master' into cluster-resize 2018-02-06 11:44:31 -06:00
Yuce Tekol
1a8bd8bcf4
Merge pull request #1086 from yuce/take-back-getting-started-frame-options
Takes back frame options in getting started docs
2018-02-06 20:41:23 +03:00
Yuce Tekol
90b69fd413
remove inverseEnabled 2018-02-06 20:39:52 +03:00
Yuce Tekol
793faa0d0e
Remove inverse-enabled 2018-02-06 20:38:51 +03:00
Yuce Tekol
5274ef01cc
Takes back frame options in getting started docs 2018-02-06 20:35:41 +03:00
Todd Gruben
a01a64aec5 remove unneeded dep 2018-02-06 10:51:03 -06:00
Matthew Jaffee
cc8733eedb
fix bug where a count query and bitmap query could return different numbers
There was a case where the Bitmap iterator logic could skip over a bit in a run
container if 1. the run container was not the first container in the bitmap, and
2. The first run in the run container had only one bit.

The bug was due to how the iterator was initialized with iterator.Seek(0) which
sets up the initial values of itr.i,j,k based on the type of the first
container. It was failing to set itr.k to -1 unless the first container was an
RLE container. itr.k is only used by RLE containers in the iterator, and must be
set to -1 when an RLE container is encountered. When Iterator.Next() encountered
the run container and itr.k was set to 0, it checked to see if itr.k <= run.last
- run.first, and if so it assumes that it was finished with the run and moved to
the next one. run.last - run.first is 0 in the case of a single bit run, so that
bit was skipped. After this, itr.k is set to -1 and all further iteration
proceeds as expected.
2018-02-06 10:26:17 -06:00
Travis Turner
2d5daaf78d
Merge branch 'master' into cluster-resize 2018-02-06 10:06:15 -06:00
Todd Gruben
eca01e4b4f replace sha1 hash with faster xxhash 2018-02-06 08:51:38 -06:00
Todd Gruben
784b0e8c55 Merge remote-tracking branch 'upstream/master' 2018-02-06 08:29:58 -06:00
Travis Turner
668689e119
ensure that the license is prepended to all source files 2018-02-05 16:35:28 -06:00
Travis Turner
20d6119906
Merge pull request #1077 from travisturner/cluster-resize-nodeid-as-name
Use NodeID instead of URI for node identification
2018-02-05 10:24:30 -06:00
Cody Soyland
902a2daf76
Merge pull request #1078 from codysoyland/diagnostics-build-constraint
Enable diagnostics via build constraint to prevent from running in tests
2018-02-05 08:55:31 -06:00
Cody Soyland
6756d97089 Enable diagnostics via build constraint to prevent from running in tests 2018-02-02 17:32:14 -06:00
Travis Turner
346e92a91d
return 0 values for errors. panic on unmarshal node meta data 2018-02-02 15:58:51 -06:00
Travis Turner
86dbbbf393
don't require oldNode in SetCoordinator() 2018-02-02 15:58:51 -06:00
Travis Turner
216ba7a41e
Use NodeID instead of URI for node identification 2018-02-02 15:58:46 -06:00
Travis Turner
143d3de66b
Merge pull request #1073 from travisturner/fix-framerestore-test
Fix FrameRestore test
2018-01-29 15:59:42 -06:00
alanbernstein
0dee49279c
Merge pull request #1075 from alanbernstein/readme-question-link
Link to usage question issue
2018-01-29 13:57:47 -06:00
Alan Bernstein
8625c2fcdb Update wording 2018-01-29 13:44:43 -06:00
Alan Bernstein
73e0b67aee Link to usage question issue 2018-01-29 12:15:29 -06:00
Travis Turner
d3590098f6
perform FrameRestore on both nodes in test cluster 2018-01-29 11:22:28 -06:00
Travis Turner
9b8d1ad4f9
add CreateViewMessage for broadcaster 2018-01-29 11:22:19 -06:00
Travis Turner
54e3235199
Merge pull request #1070 from travisturner/cluster-resize-merge
Cluster resize merge
2018-01-25 09:40:36 -06:00
Travis Turner
27e4f19af5
Merge branch 'master' into cluster-resize-merge 2018-01-25 09:39:05 -06:00
Travis Turner
267cb05039
Merge remote-tracking branch 'upstream/cluster-resize' into cluster-resize 2018-01-25 09:35:29 -06:00
Travis Turner
b8150d345e
Merge pull request #1065 from travisturner/fix-cluster-tests
Fix cluster tests
2018-01-25 09:34:04 -06:00
Travis Turner
c3512ab784
Merge remote-tracking branch 'upstream/cluster-resize' into cluster-resize 2018-01-25 09:20:38 -06:00
Travis Turner
c6ed7345c7
Merge pull request #1068 from travisturner/node-status-mutex
add lock around Node.status to avoid race condition
2018-01-24 23:06:45 -06:00
Todd Gruben
717530f007 merge 2018-01-24 18:37:30 -06:00
Travis Turner
878b188155
add accessor method for Node.status 2018-01-24 17:03:58 -06:00
Travis Turner
88fa51e6bf
add lock around Node.status to avoid race condition 2018-01-24 16:03:36 -06:00
Travis Turner
0cb8b77640
fix potential race condition: reading from a nil channel 2018-01-23 16:32:32 -06:00
Travis Turner
f12527d535
put a mutex around Cluster.State 2018-01-23 16:00:32 -06:00
Travis Turner
1b0fcb0e5a
move cluster Main test helpers to the test package 2018-01-23 12:38:14 -06:00
Travis Turner
2fdc8048c5
Merge branch 'master' into cluster-resize 2018-01-23 12:17:40 -06:00
Yuce Tekol
ee503c455a
Merge pull request #1056 from yuce/1045-use-multinode-cluster-in-tests
Uses NewServerCluster method in tests
2018-01-23 19:12:25 +03:00
Travis Turner
953e2ea42f
Merge pull request #1063 from travisturner/import-keys
WIP: Modify `pilosa import` to support string rows/columns
2018-01-22 18:05:47 -06:00
Travis Turner
5fa7dfd63d
allow for QueryResultTypeNil 2018-01-22 18:04:41 -06:00
Travis Turner
d8559ae469
refactor to remove BitK (in favor of Bit) 2018-01-22 15:35:10 -06:00
Travis Turner
a56410a70b
WIP: Modify pilosa import to support string rows/columns
This PR adds a flag `pilosa import --string-keys=true` which treats the
payload CSV as comma separated strings.
2018-01-22 15:34:45 -06:00
Travis Turner
7c34c82eca
Merge pull request #1064 from travisturner/queryresponse-type
Add QueryResult.Type to protobuf message to distiguish results at the client
2018-01-22 15:31:15 -06:00
Travis Turner
56ad70e149
Add QueryResult.Type to protobuf message to distiguish results at the client 2018-01-22 15:27:49 -06:00
Todd Gruben
e1735a60ec added alloc logging 2018-01-19 12:15:15 -06:00
Todd Gruben
da5f8f11bb benchmark for snapshotting 2018-01-19 11:58:20 -06:00
Travis Turner
e719e62409
Merge pull request #1059 from travisturner/cluster-resize
remove deprecated MustNewRunningServer
2018-01-19 08:22:53 -06:00
Travis Turner
d64a107ddd
remove deprecated MustNewRunningServer 2018-01-17 13:26:20 -06:00
Travis Turner
12ee4f86d5
Merge pull request #1058 from travisturner/cluster-resize
Merge master into cluster-resize
2018-01-17 13:13:18 -06:00
Travis Turner
c0fab2bcee
Merge branch 'master' into cluster-resize 2018-01-17 12:55:12 -06:00
Yuce Tekol
be24428367
Uses NewServerCluster method in tests 2018-01-17 14:43:58 +03:00
Matthew Jaffee
3e801d0fc1
Merge pull request #1055 from jaffee/enterprise
Enterprise
2018-01-16 16:52:13 -06:00
Travis Turner
0ad65e64b7
use json:omitempty on Pair.Key 2018-01-16 11:21:02 -06:00
Travis Turner
64e1b95910
fix test TestHandler_Query_Pairs_JSON 2018-01-16 11:21:02 -06:00
Ben Johnson
234d40fe96
Enterprise support. 2018-01-16 11:21:01 -06:00
Matthew Jaffee
3894e571d8
Merge pull request #1053 from jaffee/test-cluster-helper
add NewServerCluster(size int) method to pilosa/test
2018-01-16 09:53:36 -06:00
Matthew Jaffee
5799c10cd1
rename openPort, and some small refactors 2018-01-16 09:41:03 -06:00
Matthew Jaffee
673a290255
make diagnostics false in cluster test 2018-01-15 10:40:36 -06:00
Yuce Tekol
8a82a5c9a3
Merge pull request #1039 from yuce/1034-version-endpoint-modification
[Trivial] [Low priority] Makes /version endpoint semver-compatible
2018-01-15 18:41:32 +03:00
Matthew Jaffee
0ac8648ea9
add NewServerCluster(size int) method to pilosa/test 2018-01-12 16:29:32 -06:00
Matthew Jaffee
df5840936c
Merge pull request #1051 from jaffee/release-protection
don't build release if git status is not clean
2018-01-12 10:59:27 -06:00
Matthew Jaffee
b5df590bd0
don't build release if git status is not clean 2018-01-11 17:14:31 -06:00
Travis Turner
787d2830b3
Merge pull request #1048 from travisturner/syncer-stats
add some statsd calls to HolderSyncer
2018-01-11 15:26:01 -06:00
Travis Turner
3fc2f27710
add some statsd calls to HolderSyncer 2018-01-11 14:57:45 -06:00
Matthew Jaffee
bd2c9b8d1a
Merge pull request #1043 from jaffee/readlocks-master
Readlocks master
2018-01-09 16:07:20 -06:00
Matthew Jaffee
e5c2d3e5d8
update gopkg.lock 2018-01-09 14:05:30 -06:00
Matthew Jaffee
664fb7cad0
convert some locks to rlocks 2018-01-09 13:55:29 -06:00
Matthew Jaffee
59bd2da93f
fix a number of data races
datadog statsd client contained a race condition - was fixed in master

Server.Logger contained a race where multiple loggers could write to the same
output io.Writer

TestMain_FrameRestore contained a race where it tried to change a cluster's
nodes while it was running (which conflicted with antiEntropy reading that
state).
2018-01-09 13:31:17 -06:00
Yuce Tekol
bc49d1e6fd
Makes /version endpoint semver-compatible 2018-01-09 21:15:36 +03:00
Travis Turner
8bce8171af
Merge pull request #1036 from travisturner/minor-fixes
getting some minor fixes out of my stash
2018-01-04 21:19:00 -06:00
Travis Turner
e57c125c08
getting some minor fixes out of my stash 2018-01-04 10:45:04 -06:00
Travis Turner
3631cfc314
Merge pull request #1014 from travisturner/cluster-resize-gossip-config
Cluster resize gossip config
2018-01-03 11:20:20 -06:00
Travis Turner
311f9699b7
Merge pull request #1035 from travisturner/disable-diagnostics-in-server-tests
disable diagnostics in server tests
2018-01-02 15:41:40 -06:00
Travis Turner
149e8124db
disable diagnostics in server tests 2018-01-02 15:10:02 -06:00
Travis Turner
767c52dd16
Merge pull request #1030 from travisturner/tutorial-field-fixes
apply comments in #1022
2018-01-02 12:33:57 -06:00
Cody Soyland
78033a2374
Merge pull request #1025 from codysoyland/diagnostics-uptime-caps
Rename diagnostics metric "uptime" to "Uptime"
2018-01-02 11:04:25 -06:00
Matthew Jaffee
e72d596ad6
Merge pull request #923 from jaffee/test-helpers
add test helper for starting a new pilosa instance
2017-12-29 16:46:48 -06:00
Travis Turner
780078e427
add context to errors in gossip member set 2017-12-28 10:37:58 -06:00
Travis Turner
776dc79050
Merge pull request #1032 from travisturner/memberlist-wan-config
change gossip config from DefaultLocalConfig to DefaultWANConfig
2017-12-23 19:39:44 -06:00
Travis Turner
009a2482b4
change gossip config from memberlist.DefaultLocalConfig to memberlist.DefaultWANConfig 2017-12-22 17:06:24 -06:00
tgruben
e4f5494db2
Merge pull request #1027 from tgruben/rle-optimize
added binary search to runAdd
2017-12-22 13:26:27 -06:00
Travis Turner
4d61800c38
apply comments in #1022 from cody 2017-12-22 10:20:00 -06:00
Travis Turner
cea8c10381
Merge pull request #1026 from travisturner/tutorial-row-col-attributes
basic row/col attribute tutorial
2017-12-22 10:17:40 -06:00
Todd Gruben
8547f1a2a9 gofmted 2017-12-21 15:30:31 -06:00
Todd Gruben
89714c706d added binary search to runAdd 2017-12-21 15:12:35 -06:00
Travis Turner
1f06bb0a7e
basic row/col attribute tutorial 2017-12-21 14:16:26 -06:00
Travis Turner
2772daa395
Merge pull request #1024 from travisturner/cluster-resize-holder-open-race
make sure the holder has opened before merging NodeStatus
2017-12-21 09:07:36 -06:00
Cody Soyland
24a0c76ba5 Rename diagnostics metric "uptime" to "Uptime" to be consistent with other diagnostics metrics. 2017-12-21 07:57:08 -06:00
Travis Turner
17484fd73e
make sure the holder has opened before merging NodeStatus 2017-12-20 16:42:58 -06:00
Travis Turner
ed14ddf4d6
Merge pull request #1023 from travisturner/bsi-tutorial-nav
add nav to the markdown header
2017-12-20 09:19:53 -06:00
Yuce Tekol
a7c76f09ad
Merge pull request #1016 from yuce/990-diagnostics-schema-fields
Added BSIFieldCount diagnostics; refactored schema diagnostics
2017-12-20 07:48:10 +03:00
Travis Turner
bd5c1028f8
add nav to the markdown header 2017-12-19 17:30:18 -06:00
Travis Turner
91ba60efd3
Merge pull request #1022 from travisturner/bsi-tutorial
BSI tutorial
2017-12-19 17:25:25 -06:00
tgruben
93102a94ae
Merge pull request #1020 from tgruben/vetfix
RIP container_type
2017-12-19 16:11:12 -06:00
Cody Soyland
8135eca1ca
Merge pull request #1019 from codysoyland/1018-handler-error
Close HTTP handler gracefully (Fixes #1018)
2017-12-19 16:10:56 -06:00
Travis Turner
88e65142ad
fix typo. add link to range query operators. 2017-12-19 15:37:00 -06:00
Yuce Tekol
d6fe6e18af
Merge pull request #1015 from yuce/988-989-diagnostics-os-mem-info
Adds CPU and mem info to the diagnostics payload. Implements #988, #989
2017-12-20 00:01:22 +03:00
Yuce Tekol
bdf813d7ee
update 2017-12-19 23:59:04 +03:00
Travis Turner
8d0521fd10
setup -> set up 2017-12-19 14:39:04 -06:00
Travis Turner
660d84228b
tutorial for BSI Field usage 2017-12-19 14:38:20 -06:00
tgruben
63a3df1634
Merge pull request #1017 from tgruben/container-bench
added benchmark for various container usage patterns
2017-12-19 13:07:23 -06:00
Todd Gruben
065c82f737 passed deadcode check 2017-12-19 11:30:17 -06:00
Todd Gruben
cd4a30e671 unconvert warnings corrected 2017-12-19 11:18:46 -06:00
Travis Turner
52897421ad
fix comment 2017-12-19 11:07:34 -06:00
Cody Soyland
2345ae0004 Close HTTP handler gracefully (Fixes #1018) 2017-12-19 11:01:36 -06:00
Todd Gruben
136dc4ca2e finished govet issues 2017-12-19 10:49:00 -06:00
Todd Gruben
1dbe64da3c made sure Linear and Reverse delt with same bits 2017-12-19 10:45:27 -06:00
Todd Gruben
449b63783d merge error check 2017-12-19 10:36:28 -06:00
Todd Gruben
28d590c575 cleaned up some golint warnings 2017-12-19 10:32:39 -06:00
tgruben
868d28b2d5
Merge pull request #1012 from tgruben/errcheck
added error checking to WriteTo
2017-12-19 10:26:07 -06:00
Todd Gruben
d0d6d3d6b6 added benchmarks for runs for intersect count 2017-12-19 07:52:53 -06:00
Todd Gruben
4ceaed5316 missed one 2017-12-19 07:21:24 -06:00
Todd Gruben
0f3d26bd30 addressed jaffee suggestions; tweaked parameters 2017-12-19 07:15:40 -06:00
Travis Turner
6b3f4d1a64
Merge branch 'master' into cluster-resize
Refactored LocalID/ClusterID for use with Topology and Coordinator.
2017-12-18 15:39:50 -06:00
Todd Gruben
ccf57e23cd removed overlap calc 2017-12-18 15:33:22 -06:00
Todd Gruben
89a42c7fe2 corrected offset value 2017-12-18 15:18:54 -06:00
Todd Gruben
a2195396ca fixed varible overwrite 2017-12-18 15:01:52 -06:00
Todd Gruben
155472b3db added benchmark for various container usage patterns 2017-12-18 14:01:11 -06:00
Yuce Tekol
7355f97b62
Added BSIFieldCount diagnostics; refactored schema diagnostics 2017-12-18 18:07:31 +03:00
Yuce Tekol
94360e77e3
Adds CPU and mem info to the diagnostics payload. Implements #988, #989 2017-12-18 16:22:38 +03:00
Yuce Tekol
0ad4272b35
Merge pull request #1013 from yuce/987-diagnostics-cluster-id
Adds local and cluster IDs
2017-12-16 13:42:40 +03:00
Travis Turner
d2d0756f4a
Define default config values for pilosa server in NewConfig rather than
flags. Based on work done in #885.
2017-12-15 15:07:02 -06:00
Travis Turner
78cddbd0c7
Add the rest of the available memberlist configuration options
into pilosa.Config.Gossip.
2017-12-15 12:37:51 -06:00
Yuce Tekol
1448171a2c
Adds local and cluster IDs 2017-12-15 18:12:28 +03:00
Todd Gruben
6bec75fc31 applied travis suggestions 2017-12-15 09:08:53 -06:00
Cody Soyland
eadc57a1d8
Merge pull request #1010 from codysoyland/1009-goveralls-ci-failures
Use `go test` instead of `goveralls` as main CI test command
2017-12-14 12:02:12 -06:00
Cody Soyland
0f48e4ee17 Use go test instead of goveralls as main CI test command. Call goveralls in after_success block. Fixes #1009. 2017-12-13 15:35:09 -06:00
Todd Gruben
e2064f52b1 added error checking to WriteTo 2017-12-13 15:08:03 -06:00
tgruben
32c5b20748
Merge pull request #1004 from travisturner/cluster-resize-test
WIP: add tests for cluster resize
2017-12-13 09:08:09 -06:00
Travis Turner
2afbdba1c5
add lock protection around gossip.memberlist and holder.indexes 2017-12-13 08:54:11 -06:00
Yuce Tekol
8d587d753c
Merge pull request #1007 from yuce/getting-started-update
remove frame options from getting started
2017-12-13 17:32:42 +03:00
Yuce Tekol
41be85ba30
Merge pull request #981 from yuce/978-deprecate-index-time-quantum
Deprecate index time quantum in the docs; resolves #978
2017-12-13 17:32:22 +03:00
Yuce Tekol
ab19576dbb
remove frame options from getting started 2017-12-13 17:27:08 +03:00
Cody Soyland
43e4f98fe4
Merge pull request #1006 from codysoyland/version-bump-docs
Release v0.8.3
2017-12-12 17:06:50 -06:00
Cody Soyland
2bf1e1a4e3 Release v0.8.3 2017-12-12 16:43:44 -06:00
Travis Turner
0342da92bb
WIP: add tests for cluster resize
This commit adds support for allocating a gossip transport
and a server listener prior to opening server (and cluster).
Doing that allows tests to use a dynamically allocated port
by supplying bind port: 0.
2017-12-12 16:27:47 -06:00
Matthew Jaffee
361e18e79d
Merge pull request #1002 from jaffee/unmapped-mem-master
Unmapped mem master
2017-12-11 11:26:39 -06:00
Travis Turner
9667a04cad
Merge branch 'master' into cluster-resize 2017-12-08 17:56:31 -06:00
Travis Turner
e8b64dba56
Merge pull request #1001 from travisturner/973-sendsync
973 sendsync
2017-12-08 17:00:46 -06:00
Travis Turner
dd390453ac
improve error messages in client.SendMessage() 2017-12-08 16:50:17 -06:00
Travis Turner
cf1e41faf1
Merge branch 'master' into cluster-resize 2017-12-08 15:22:12 -06:00
Matthew Jaffee
4785b0e793
add container types to other tests (though they were passing already) 2017-12-08 09:56:44 -06:00
Matthew Jaffee
907aa3495f
add container types and set c.n to get tests working 2017-12-08 09:54:24 -06:00
Matthew Jaffee
489b7a59c4
protect against accessing pointers to memory which was unmapped 2017-12-08 09:53:54 -06:00
Travis Turner
637111a76c
Change Broadcaster.SyndSync to send direct via http
as opposed to using memberlist's gossip broadcast.
Introduce a Gossiper interface for SendAsync gossip messages.
2017-12-08 09:00:47 -06:00
Michael Baird
21072a665f
refactor same node URI check in SendSync 2017-12-08 08:27:09 -06:00
Michael Baird
04790f70f2
moved the broadcast handler receive message process to the handler ProcessClusterMessage 2017-12-08 08:27:09 -06:00
Michael Baird
814bc40a16
return the error from /cluster/message 2017-12-08 08:22:59 -06:00
Michael Baird
e296a0d648
Client method for the SendSync /cluster/message 2017-12-08 08:22:59 -06:00
Michael Baird
013d32099e
New /cluster/message endpoint handles all SendSync Messages 2017-12-08 08:22:59 -06:00
Michael Baird
9cf994bda7
Use the Broadcast Handler's SendSync implementation rather than Gossip 2017-12-08 08:22:59 -06:00
Michael Baird
29bd0319dc
Create a SendSync Interface for the Broadcast handler 2017-12-08 08:22:59 -06:00
Travis Turner
5af377e56a
Merge pull request #992 from travisturner/custom-gossip-transport
Resume test: TestMain_SendReceiveMessage
2017-12-07 16:13:41 -06:00
tgruben
29776dbc5c
Merge pull request #999 from tgruben/resize
adjust to single http client
2017-12-07 15:22:21 -06:00
Todd Gruben
e6adb361b9 cleanup logging 2017-12-07 15:09:42 -06:00
Todd Gruben
9565db43a8 add sort order to URI addition 2017-12-07 14:11:49 -06:00
Todd Gruben
c14bc29041 added logging for node membership 2017-12-07 11:17:37 -06:00
Todd Gruben
f17a399a37 adjust to single http client 2017-12-07 08:33:26 -06:00
Travis Turner
0f971f7bc6
Merge pull request #950 from raskle/914-syncblock-maxwrites
group the write operations in syncBlock by MaxWritesPerRequest
2017-12-06 14:02:07 -06:00
Yuce Tekol
0f094ce316
Merge pull request #901 from yuce/871-gossip-port-doc
Added single cluster config; implements #871
2017-12-06 20:33:30 +03:00
Yuce Tekol
c6e30f1e37
Merge pull request #972 from yuce/update-input-definition-import-doc
TRIVIAL: Fixes the import data section in the input definition docs
2017-12-06 20:32:49 +03:00
Cody Soyland
0564950123
Merge pull request #979 from codysoyland/876-range-edge-cases
Fix edge case with Range() calls outside field Min/Max. Fixes #876.
2017-12-05 08:57:03 -06:00
Travis Turner
83ba680f83
Merge pull request #995 from travisturner/merge-master
Merge master into cluster-resize
2017-12-04 22:33:34 -06:00
Travis Turner
c9886b049b
Merge branch 'master' into cluster-resize working branch. 2017-12-04 22:18:57 -06:00
Travis Turner
4842504968
Merge pull request #985 from travisturner/cleanup-fragments
Add HolderCleaner and view.DeleteFragment
2017-12-04 21:04:43 -06:00
Travis Turner
e6ff67bd83
add index/frame/view info to delete fragment log information 2017-12-04 18:03:23 -06:00
Travis Turner
073848ae31
Make sure node gets removed from all nodeSets after resize 2017-12-04 18:03:23 -06:00
Travis Turner
59cdd5dde9
Add HolderCleaner and view.DeleteFragment to support post-resize cleanups
Add tests for view.DeleteFragment and HolderCleaner
2017-12-04 18:03:22 -06:00
Travis Turner
5aa905b9a1
Merge pull request #935 from travisturner/cluster-resize-test-setvalue
add SetFieldValue() method to TestCluster and use in tests
2017-12-04 17:31:49 -06:00
Travis Turner
9b54259cd7
Resume test: TestMain_SendReceiveMessage
Create a custom memberlist NetTransport (which will bind to an available
port when port = 0 in the configuration). This allows us to bind
to dynamic ports in tests while at the same time determining a valid
seed for the cluster.
2017-12-04 14:56:21 -06:00
tgruben
29aca37d83
Merge pull request #991 from tgruben/single-http-client
refactored httpclient handling
2017-12-04 12:24:48 -06:00
Todd Gruben
e7d64c4f48 limit httpclient instances on executor tests 2017-12-04 12:17:41 -06:00
Todd Gruben
f051f7ccea refactored httpclient handling 2017-12-01 16:00:12 -06:00
Travis Turner
9f6bae94d6
Merge pull request #982 from travisturner/holder-wait
Holder wait
2017-11-29 15:33:17 -06:00
Travis Turner
91c7abfa9a
remove outdated TODO 2017-11-28 16:47:40 -06:00
Travis Turner
8228ef2382
Add a Cluster.Static override for tests to treat static nodes as
Coordinator.
Refactor the Server.joining channel to be in Cluster instead.
2017-11-28 16:40:05 -06:00
Travis Turner
ccdd6262c5
add error logging for non-topology nodeJoin 2017-11-28 12:43:49 -06:00
Travis Turner
ae63adfaac
let remote nodes know that its safe to open Holder when launching based on existing taxonomy 2017-11-27 11:06:03 -06:00
Travis Turner
013cd0cd95
refactor resize instruction logic to support multi-index. wait to open holder on non-coordinator nodes. 2017-11-27 11:06:03 -06:00
Travis Turner
f2c32f8ec9
add logging support to ResizeJob 2017-11-27 11:06:03 -06:00
Travis Turner
bd511dae80
ensure that holder opens before node is deemed ready 2017-11-27 11:06:03 -06:00
Travis Turner
a13db570cc
WIP: Wait for nodeState on Holder.Open().
Implement prefect in Cluster so a node can start http listener in a
restricted mode.
Adjust tests; particularly start test.Holder in state Normal.

TODO:
- [ ] fix test TestMain_SendReceiveMessage
- [ ] add additional tests for `nodeState`
2017-11-27 11:06:03 -06:00
Travis Turner
a98b862fca
add /cluster/resize/remove-node endpoint 2017-11-27 11:06:02 -06:00
Yuce Tekol
390448c342
fix input definition file name 2017-11-22 20:22:12 +03:00
Cody Soyland
088847dcef
Merge pull request #980 from codysoyland/977-docker-bind-localhost
Bind the handler to all interfaces (0.0.0.0) in Dockerfile. Fixes #977.
2017-11-21 20:21:03 -06:00
Yuce Tekol
9de9b7cc30
Deprecate index time quantum in the docs; resolves #978 2017-11-21 23:36:20 +03:00
Cody Soyland
5f4545eeb2 Fix edge case with Range() calls outside field Min/Max. Fixes #876. 2017-11-21 13:43:44 -06:00
Travis Turner
f0763a5089
Merge pull request #963 from travisturner/set-coordinator
add set-coordinator endpoint
2017-11-20 18:27:44 -06:00
Yuce Tekol
450a4c0724
Fixes the import data section in the input definition docs 2017-11-17 18:27:06 +03:00
Travis Turner
ec135a51b6
Merge pull request #964 from travisturner/temp-disable-go-master-build
Temporarily disable Go master CI as builds are failing due to possibl…
2017-11-15 09:29:21 -06:00
Cody Soyland
2517b994a1
Temporarily disable Go master CI as builds are failing due to possible Go bug (See #956) 2017-11-15 09:28:29 -06:00
Travis Turner
426992bc59
add set-coordinator endpoint 2017-11-15 09:13:52 -06:00
Travis Turner
d741649d00
Merge pull request #946 from travisturner/buffer-joining-nodes
WIP: don't block joining nodes while coordinator loads data.
2017-11-15 08:04:00 -06:00
Michael Baird
59035883f4 group the write operations in syncBlock by MaxWritesPerRequest 2017-11-10 15:03:23 -06:00
Travis Turner
212628b220
adjust tests to include Cluster.ListenForJoins() 2017-11-10 11:38:16 -06:00
Travis Turner
453bbc996c
adjust Holder.Peek() and add tests for it 2017-11-10 10:38:49 -06:00
Travis Turner
9d87019762
WIP: don't block joining nodes while coordinator loads data.
Implements a Holder.Peek() function, and breaks out
Cluster.ListenForJoins() into a separate method that can be started
after the Holder finishes loading data.

TODO:
- [ ] test Holder.Peek()
2017-11-10 09:14:13 -06:00
Travis Turner
351e43db41
Merge pull request #937 from travisturner/merge-master
Merge master into cluster-resize
2017-11-08 10:20:53 -06:00
Travis Turner
e641aa1d8a
Merge branch 'master' into 'cluster-resize' 2017-11-07 15:00:11 -06:00
Travis Turner
fee1b55838
replace test ErrRangeCacheNotAllowed with ErrRangeCacheAllowed 2017-11-06 16:03:23 -06:00
Travis Turner
b11a6dd1a1
Merge pull request #932 from travisturner/nodeid-tags
891 nodeid tags (from #897)
2017-11-06 14:56:45 -06:00
Travis Turner
ec5ac629cd
porting the remaining changes from PR #897 2017-11-06 14:48:35 -06:00
Travis Turner
7e797efdc2
Allow CacheType to be set for a RangeEnabled frame (to apply to the standard frame) 2017-11-06 14:32:20 -06:00
Travis Turner
0d5a2e7bfd
add SetFieldValue() method to TestCluster and use in tests 2017-11-06 10:51:13 -06:00
Travis Turner
53fa54d3d3
891 nodeid tags (from #897) 2017-11-06 09:17:50 -06:00
Travis Turner
7116232625
Merge pull request #931 from travisturner/uri-json-tags
add json tags to uri struct
2017-11-06 08:46:22 -06:00
Travis Turner
f94a2a0cfc
add json tags to uri struct 2017-11-06 08:38:08 -06:00
Travis Turner
638e328455
Merge pull request #929 from travisturner/cluster-resize-tests
Add Cluster resize tests.
2017-11-06 08:34:46 -06:00
Travis Turner
5071fd9e5d
Fix error format on slices.
These tests were failing on `Go:master` (passing on `Go:1.8` and
`Go:1.9`)
2017-11-03 18:14:17 -05:00
Travis Turner
c7c1be6813
change read lock to write lock 2017-11-03 17:43:05 -05:00
Travis Turner
73b9d9fd85
Add Cluster resize tests.
Consolidate schema creation into Holder.ApplySchema.
Add view names to proto schema.
2017-11-03 17:22:39 -05:00
Travis Turner
e9baaea2d3
Merge pull request #927 from travisturner/cluster-resize-sync-schema
include Schema in pb.ResizeInstructions
2017-11-03 11:31:12 -05:00
Travis Turner
7d300e7080
include Schema in pb.ResizeInstructions 2017-11-03 11:21:53 -05:00
Travis Turner
a8c507cbae
Merge pull request #917 from tgruben/restrictedrouter
added endpoint protection for cluster resize
2017-11-01 14:12:52 -05:00
Matthew Jaffee
05254ad11e
add test helper for starting a new pilosa instance
Pilosa runs on ephemeral ports with temporrary storage.
2017-11-01 13:21:06 -05:00
Travis Turner
da0184f728
Adjust comments. Change DefaultSecurityManager to NopSecurityManager. 2017-10-31 13:56:58 -05:00
Todd Gruben
fc829b08e8 made endpoint available for resize 2017-10-31 12:12:20 -05:00
Todd Gruben
9b7adde692 added endpoint protection for cluster resize 2017-10-31 11:32:08 -05:00
Travis Turner
3bdcc16dbc
Merge pull request #913 from travisturner/abort-resize-endpoint
endpoint to abort a cluster resize that is in progress
2017-10-30 15:51:06 -05:00
Travis Turner
fb08fd3902
endpoint to abort a cluster resize that is in progress 2017-10-30 15:50:22 -05:00
Michael Baird
3539c6ffb5 Fixed overwriting standard with inverse max slice 2017-10-30 15:28:12 -05:00
Travis Turner
c360ca2975
Merge pull request #912 from travisturner/copy-fragment-data
Copy fragment data
2017-10-30 14:41:20 -05:00
Travis Turner
fa61824975
Merge pull request #908 from travisturner/update-status-schema
Update status schema
2017-10-30 14:39:52 -05:00
Travis Turner
f2d28a1df9
make note of a possible race condition 2017-10-30 14:28:45 -05:00
Travis Turner
ed7dcdcdef
rename NodeState to ClusterState 2017-10-30 13:09:27 -05:00
Travis Turner
f4b0729458
Rename structs and funcs.
NodeSet -> MemberSet
URISet -> NodeSet
AddNode -> AddNodeBasicSorted
AddHost -> AddNode
2017-10-30 13:03:55 -05:00
Travis Turner
ed1b4fcc2e
Copy fragment data from source nodes in resize instruction. 2017-10-30 13:01:57 -05:00
Travis Turner
2f6c4509c2
remove references to cluster.poll-interval 2017-10-30 09:20:09 -05:00
Travis Turner
f49b2f9b99
Adjust /status and /schema endpoints. Tried/failed to deprecate /slices/max (client is using it for backups). 2017-10-30 09:05:59 -05:00
Travis Turner
2bd0677df9
Remove MaxSlice polling.
Add Schema to proto.
Update MaxSlices in proto to include both standard and inverse.
Update LocalStatus (shared in gossip) to include MaxSlices and Schema.
Encode InputDefinitions with Index.

TODO:
- make sure InputDefinitions are considered in LocalStatus merge.
- decide what to do about `/slices/max` endpoint. client.backup is using
  it.
2017-10-26 23:48:40 -05:00
Travis Turner
097b866c37 Merge pull request #907 from travisturner/remove-frameschema
Remove FrameSchema. Move Fields to the Frame struct.
2017-10-26 16:03:36 -05:00
Travis Turner
cd8542ca30
Remove FrameSchema. Move Fields to the Frame struct. 2017-10-26 11:11:05 -05:00
Travis Turner
deed9adfe4
Fix existing tests 2017-10-25 11:53:11 -05:00
Travis Turner
a8871ada6a
Convert Host to URI.
Fix all compile errors.
2017-10-25 11:52:55 -05:00
Travis
f1e3ac90d4
Determine cluster membership via gossip.
Handle resize cluster events.
Add Toplogy support.
Refactor FrameOptions.
Add tests.
2017-10-25 00:27:30 -05:00
Yuce Tekol
bbd9aedf0f
fix gossip port text 2017-10-24 23:06:25 +03:00
Yuce Tekol
89c641ed24
Added single cluster config; implements #871 2017-10-24 16:36:39 +03:00
1710 changed files with 580387 additions and 42186 deletions

View file

@ -1 +0,0 @@
.*

View file

@ -1,16 +0,0 @@
For bugs, please provide the following:
### Expected behavior
### Actual behavior
### Steps to reproduce the behavior
### Information about your environment (OS/architecture, CPU, RAM, cluster/solo, configuration, etc.)
For feature requests, please provide the following:
### Description
### Success criteria (What criteria will consider this ticket closeable?)

View file

@ -1,24 +0,0 @@
## Overview
[Describe what this pull request addresses.]
Fixes #
## Pull request checklist
- [ ] I have read the [contributing guide](https://github.com/pilosa/pilosa/blob/master/CONTRIBUTING.md).
- [ ] I have agreed to the [Contributor License Agreement](https://cla-assistant.io/pilosa/pilosa).
- [ ] I have updated the [documentation](https://github.com/pilosa/pilosa/tree/master/docs).
- [ ] I have resolved any merge conflicts.
- [ ] I have included tests that cover my changes.
- [ ] All new and existing tests pass.
## Code review checklist
This is the checklist that the reviewer will follow while reviewing your pull request. You do not need to do anything with this checklist, but be aware of what the reviewer will be looking for.
- [ ] Ensure that any changes to external docs have been included in this pull request.
- [ ] If the changes require that minor/major versions need to be updated, tag the PR appropriately.
- [ ] Ensure the new code is [properly commented](https://github.com/golang/go/wiki/CodeReviewComments#doc-comments) and follows [Idiomatic Go](https://dmitri.shuralyov.com/idiomatic-go).
- [ ] Check that tests have been written and that they cover the new functionality.
- [ ] Run tests and ensure they pass.
- [ ] Build and run the code, performing any applicable integration testing.

77
.github/workflows/cd.yml vendored Normal file
View file

@ -0,0 +1,77 @@
name: CD
on:
push:
branches: ["master"]
workflow_dispatch:
jobs:
validate:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: "^1.19.1"
- run: go version
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
args: --timeout=5m
- name: go vet
run: go vet ./...
- name: test
run: go test ./...
release:
needs: validate
runs-on: ubuntu-latest
outputs:
version: ${{ steps.semrel.outputs.version }}
steps:
- name: go-semantic-release
id: semrel
uses: go-semantic-release/action@v1.17.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
build:
needs: release
runs-on: ubuntu-latest
strategy:
matrix:
goos:
- "darwin"
- "linux"
- "windows"
goarch:
- "amd64"
- "arm64"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: "^1.19.1"
- name: build
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -o ./build/${{ matrix.goos }}-${{ matrix.goarch }}
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./build/${{ matrix.goos }}-${{ matrix.goarch }}
asset_name: ${{ matrix.goos }}-${{ matrix.goarch }}
tag: ${{ github.ref }}

57
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,57 @@
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the workflow will run
on:
pull_request:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
validate-title:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: go-semantic-release/action@v1
id: semrel
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
dry: true
# golangci-lint must be run separately from "validate" as there are go mod issues if you run it after the vet
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.19
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
# version: v1.29
args: --timeout=8m
validate:
name: Code Checks
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: "^1.19.1"
- run: go version
- name: go vet
run: go vet ./...

25
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,25 @@
name: Release
on: workflow_dispatch
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
goos:
- "darwin"
- "linux"
goarch:
- "amd64"
- "arm64"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: "^1.19.1"
- name: build
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -o ./build/${{ matrix.goos }}-${{ matrix.goarch }}

81
.gitignore vendored
View file

@ -4,3 +4,84 @@ vendor
.protoc-gen-gofast
.DS_Store
build
*~
release-pilosa-fsck.*.*.tar.gz
/log.*
/tourna.log.*
pilosa
/featurebase
*.dot
.idea/
.*.swp
.terraform/
*.tfstate
launch.json
.terraform.lock.hcl
__pycache__/
report.xml
outputs.json
builds/
*.tfstate.backup
.vscode
batch/testdata/batch*.out
idk/testdata/idk*.out
idk/testenv/certs/*
# copy of .gitignore from archived idk repo
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
vendor
.terraform
terraform.tfstate*
bin
build
testenv
.pulled
pilosa-sec-data-idk
.idea/
tags.dot
*.log
*.swp
*__debug_bin
# SQL3
/sql3/sql3.html
staticcheck.conf
.quick
dax/dax-data
coverage-from-docker
*.client_id.txt

747
.gitlab/.gitlab-ci.yml Normal file
View file

@ -0,0 +1,747 @@
# You will see a couple of instances of:
# PKG_LIST=$(go list ./... | grep -Ev 'internal/clustertests|simulacraData|batch|idk|v3/dax/test/dax' | paste -s -d, -)
# This gets us a package list, comma-separated, which excludes the batch
# and IDK tests, and a couple of subdirs with specialized stuff. We can
# then use this with -coverpkg, or we can use ${PKG_LIST//,/ } to get a
# space-separated list for use with `go test` to run the tests for those
# directories only.
include:
- local: /.gitlab/batch-ci.yml
- template: Security/SAST.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
default:
retry:
max: 2 # This is confusing but this means "3 runs at max".
when:
- unknown_failure
- api_failure
- runner_system_failure
- job_execution_timeout
- stuck_or_timeout_failure
variables:
GOVERSION: "1.19.3"
GOFUTURE: "latest"
CI_IMAGE: "${CI_REGISTRY_IMAGE}/ci-builder:0.0.1"
CI_PRE_CLONE_SCRIPT: |
set -x
stages:
- ci_image_build
- lint
- test
- build
- post build
- integration
- gauntlet
- performance
- nonblocking
- cleanup_build
gosec-sast:
allow_failure: false
before_script:
- export GOPRIVATE=github.com/molecula/*
- apk add openssh-client
- eval $(ssh-agent -s)
- echo "$FB_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- git config --global --add url."ssh://git@github.com/".insteadOf "https://github.com/"
- ssh-keygen -F github.com || echo "$SSH_KNOWN_HOSTS_HASHED" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
## securego/gosec works for scanning, but not converting to the gitlab report format.
- go install github.com/securego/gosec/v2/cmd/gosec@v2.12.0
- gosec -fmt=json -out=gosec.json -tests ./... || true
## gitlab's wrapper for gosec works for converting, but not for scanning.
- go install 'gitlab.com/gitlab-org/security-products/analyzers/gosec@v1.4.0'
- gosec convert gosec.json > gl-sast-report.json
.go-cache:
variables:
GOPATH: $CI_PROJECT_DIR/.go
before_script:
- mkdir -p .go
cache:
# this caching strategy makes it so each branch uses the same cache
key: "$CI_COMMIT_REF_SLUG"
paths:
- .go/pkg/mod/
smoke build:
image: golang:$GOVERSION
extends: .go-cache
stage: lint
allow_failure: false
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Let's just see if it compiles... (sometimes the linter gives unclear errors if it doesn't)"
- go build ./...
golangci-lint:
image: golangci/golangci-lint:v1.46.2
extends: .go-cache
stage: lint
allow_failure: true
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Checking for issues in new code"
- golangci-lint run -v --timeout=8m
go mod tidy:
stage: lint
image: golang:$GOVERSION
extends: .go-cache
rules:
- if: '$CI_COMMIT_TAG == null && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web")'
script:
- go mod tidy
- git diff --exit-code -- go.mod go.sum
build lattice:
stage: test
image: node:14
variables:
AWS_PROFILE: "service-fb-ci"
AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY
CI: "false"
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
before_script:
- curl -sS "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
- unzip -qq awscliv2.zip
- ./aws/install
- aws --version
- aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
- aws configure set region "us-east-2"
- aws configure set aws_profile $AWS_PROFILE
- aws sts get-caller-identity # ensure we have a valid AWS login
script:
- cd lattice
- cache=$(find . -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum | cut -d ' ' -f 1)
- echo "'$cache'"
- echo "looking for s3://molecula-artifact-storage/lattice/$cache/build.tar.gz"
# if is for if we had a cache object in S3
# else is for if we didn't have a cache object (and have to build).
- |
if aws s3api head-object --bucket molecula-artifact-storage --key "lattice/$cache/build.tar.gz"; then
# download object, extract, name the folder `build`
aws s3 cp "s3://molecula-artifact-storage/lattice/$cache/build.tar.gz" build.tar.gz
tar -xf build.tar.gz
else # cache file not found
yarn install --frozen-lockfile # CI needs to enforce that the lockfile doesn't need to be updated
yarn build
tar -czvf "$cache.tar.gz" build/
aws s3 mv "$cache.tar.gz" "s3://molecula-artifact-storage/lattice/$cache/build.tar.gz"
touch "$CI_COMMIT_SHA"
aws s3 mv "$CI_COMMIT_SHA" "s3://molecula-artifact-storage/lattice/$cache/$CI_COMMIT_SHA"
fi
- | # Ensure that we have build directory after the caching step
if [ ! -d build ]; then
echo "no build directory, erroring out" || exit 1
fi
- mv build ../
- cd ../
- rm -r lattice
- mv build lattice
- tar -czvf lattice.tar.gz lattice
artifacts:
paths:
- lattice.tar.gz
build featurebase:
stage: test
image: golang:$GOVERSION
extends: .go-cache
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -r lattice
- tar -xvf lattice.tar.gz
- go install github.com/rakyll/statik@v0.1.7
- $GOPATH/bin/statik -src=lattice
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- |
for goos in "darwin" "linux"; do
for goarch in "amd64" "arm64"; do
GOOS="${goos}" GOARCH="${goarch}" make build FLAGS="-o featurebase_${goos}_${goarch}"
done
done
artifacts:
paths:
- featurebase_*
needs:
- job: build lattice
build fbsql amd64:
stage: test
variables:
BUILD_NAME: build_${CI_COMMIT_SHA}_${CI_CONCURRENT_ID}
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- date
- GOOS="linux" GOARCH="amd64" make docker-build-fbsql BUILD_CGO=1
- GOOS="darwin" GOARCH="amd64" make docker-build-fbsql
artifacts:
paths:
- ./build/fbsql_*
build fbsql arm64:
stage: test
variables:
BUILD_NAME: build_${CI_COMMIT_SHA}_${CI_CONCURRENT_ID}
tags:
- shell-arm64
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- date
- GOOS="linux" GOARCH="arm64" make docker-build-fbsql BUILD_CGO=1
- GOOS="darwin" GOARCH="arm64" make docker-build-fbsql
artifacts:
paths:
- ./build/fbsql_*
build amd container fb:
stage: test
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
before_script:
- echo "${DOCKER_DEPLOY_TOKEN}" | docker login -u ${DOCKER_DEPLOY_USER} --password-stdin ${CI_REGISTRY}
script:
- tag=${CI_REGISTRY_IMAGE}/featurebase:linux-amd64-${CI_COMMIT_REF_SLUG}
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- docker build --build-arg GO_VERSION=$GOVERSION --build-arg ARCH=amd64 --build-arg SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH -t $tag -f .gitlab/Dockerfile .
- docker push $tag
- echo Created docker featurebase image with tag "$tag"
needs:
- job: build featurebase
run jest tests:
stage: test
image: node:14
variables:
CI: "true"
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Testing lattice..."
- cd lattice
- npm install --force
- npm test -- --coverage --testResultsProcessor=jest-sonar-reporter
artifacts:
paths:
- lattice/coverage/lcov.info
# We run go test -race on all the standard packages, skipping the ones that have their
# own separate tests. we spin this off as nonblocking because it used to take a really
# long time and even now it's pretty slow.
run go tests race:
stage: nonblocking # don't let this job block any other jobs because it takes much longer than the other tests.
image: golang:$GOVERSION
extends: .go-cache
variables:
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_DATABASE: run_go_tests_race
POSTGRES_DB: run_go_tests_race
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_USER: postgres
POSTGRES_USER: postgres
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_HOST: postgres
services:
- postgres:14.7
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
needs: ["smoke build"] # we do block on smoke build though bc it's pretty dumb to test stuff if it doesn't build
script:
- echo "Running featurebase race tests..."
- PKG_LIST=$(go list ./... | grep -Ev 'internal/clustertests|simulacraData|batch|idk|v3/dax/test/dax' | paste -s -d, -)
- export TMPDIR=/mnt/ramdisk/test-$CI_JOB_ID
- mkdir -p $TMPDIR
- go test -race -v -timeout=10m ${PKG_LIST//,/ }
after_script:
- rm -rf /mnt/ramdisk/test-$CI_JOB_ID
tags:
- docker
# We run our base tests against $GOVERSION (a reasonably current version that we trust)
# and use shardwidth22 for them. This gives us a canary for things breaking for
# unusual shard widths.
run go tests:
stage: test
image: golang:$GOVERSION
extends: .go-cache
variables:
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_DATABASE: run_go_tests
POSTGRES_DB: run_go_tests
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_USER: postgres
POSTGRES_USER: postgres
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_HOST: postgres
services:
- postgres:14.7
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Running featurebase unit tests..."
- PKG_LIST=$(go list ./... | grep -Ev 'internal/clustertests|simulacraData|batch|idk|v3/dax/test/dax' | paste -s -d, -)
- export TMPDIR=/mnt/ramdisk/test-$CI_JOB_ID
- mkdir -p $TMPDIR
- go test -tags=shardwidth22 -timeout=10m -coverprofile=coverage.out -covermode=atomic -coverpkg=${PKG_LIST} ${PKG_LIST//,/ }
after_script:
- rm -rf /mnt/ramdisk/test-$CI_JOB_ID
artifacts:
paths:
- coverage.out
tags:
- docker
run go tests dax/test/dax:
stage: test
image: golang:$GOVERSION
extends: .go-cache
tags:
- docker
variables:
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_DATABASE: run_go_tests_dax
POSTGRES_DB: run_go_tests_dax
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_USER: postgres
POSTGRES_USER: postgres
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
FEATUREBASE_CONTROLLER_CONFIG_SQLDB_HOST: postgres
services:
- postgres:14.7
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Building FB and Datagen docker images for DAX tests"
- PKG_LIST=$(go list ./... | grep -Ev 'internal/clustertests|simulacraData' | paste -s -d, -)
- export TMPDIR=/mnt/ramdisk/test-$CI_JOB_ID
- mkdir -p $TMPDIR
- go test -coverprofile=coverage-dax-integration.out -covermode=atomic -coverpkg=${PKG_LIST} -timeout=20m ./dax/test/dax
after_script:
- rm -rf /mnt/ramdisk/test-$CI_JOB_ID
artifacts:
paths:
- coverage-dax-integration.out
# idk tests
run go tests idk race:
variables:
PROJECT: race_${CI_CONCURRENT_ID}
stage: nonblocking
retry: 1
script:
- echo "Running test-all-race"
- cd ./idk/
- echo $PROJECT
- echo $CI_COMMIT_REF_SLUG
- BRANCH_NAME=${CI_COMMIT_REF_SLUG} IDK_FEATUREBASE_TAG=${CI_COMMIT_TAG} IDK_FEATUREBASE_HASH=${CI_COMMIT_SHA} make test-all-race
after_script:
- cd ./idk/
- make save-pilosa-logs
- make shutdown
artifacts:
paths:
- ./idk/testdata/*_coverage.out
tags:
- shell
- aws
needs:
- job: build amd container fb
run go tests idk shard transactional:
variables:
IDK_DEFAULT_SHARD_TRANSACTIONAL: 1
PROJECT: shardttrans_${CI_CONCURRENT_ID}
stage: nonblocking
retry: 1
script:
- echo "Running shard transactional tests"
- cd ./idk/
- echo $PROJECT
- echo $CI_COMMIT_REF_SLUG
- BRANCH_NAME=${CI_COMMIT_REF_SLUG} IDK_FEATUREBASE_TAG=${CI_COMMIT_TAG} IDK_FEATUREBASE_HASH=${CI_COMMIT_SHA} make test-all
after_script:
- cd ./idk/
- make save-pilosa-logs
- make shutdown
artifacts:
paths:
- ./idk/testdata/*_coverage.out
- ./idk/testdata/*_logs.txt
tags:
- shell
- aws
needs:
- job: build amd container fb
run go tests idk 533:
variables:
USERNAME: fb-idk-access
PROJECT: test533_${CI_CONCURRENT_ID}
stage: nonblocking
retry: 1
script:
- echo "Running confluent 5.3.3 test-all"
- cd ./idk/
- echo $PROJECT
- echo $CI_COMMIT_REF_SLUG
- CONFLUENT_VERSION=5.3.3 BRANCH_NAME=${CI_COMMIT_REF_SLUG} IDK_FEATUREBASE_TAG=${CI_COMMIT_TAG} IDK_FEATUREBASE_HASH=${CI_COMMIT_SHA} make test-all
after_script:
- cd ./idk/
- make save-pilosa-logs
- make shutdown
tags:
- shell
- aws
artifacts:
paths:
- ./idk/testdata/*_coverage.out
needs:
- job: build amd container fb
run go tests idk sasl:
variables:
PROJECT: sasl_${CI_CONCURRENT_ID}
stage: nonblocking
retry: 1
script:
- echo "Running test-all-kafka-sasl"
- cd ./idk/
- echo $PROJECT
- echo $CI_COMMIT_REF_SLUG
- BRANCH_NAME=${CI_COMMIT_REF_SLUG} IDK_FEATUREBASE_TAG=${CI_COMMIT_TAG} IDK_FEATUREBASE_HASH=${CI_COMMIT_SHA} make test-all-kafka-sasl
after_script:
- cd ./idk/
- make save-pilosa-logs
- make shutdown
tags:
- shell
- aws
artifacts:
paths:
- ./idk/testdata/*_coverage.out
needs:
- job: build amd container fb
upload to sonarcloud:
stage: nonblocking
image: sonarsource/sonar-scanner-cli:4.7
variables:
SONAR_TOKEN: $SONAR_TOKEN
rules:
- if: '$CI_COMMIT_TAG == null && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web")'
script:
- sonar-scanner -Dsonar.projectKey=molecula_featurebase -Dsonar.organization=molecula -Dsonar.sources=. -Dsonar.host.url=https://sonarcloud.io -Dsonar.go.coverage.reportPaths=coverage*.out,results/coverage*out,idk/testdata/*coverage.out,batch/testdata/*coverage.out,coverage-from-docker/*.out -Dsonar.javascript.lcov.reportPaths=lattice/coverage/lcov.info
needs:
- job: run go tests
- job: run jest tests
- job: external lookup tests
- job: run go tests idk race
optional: true
- job: run go tests idk shard transactional
optional: true
- job: run go tests idk sasl
optional: true
- job: run go tests idk 533
optional: true
- job: run go tests batch
optional: true
- job: run go tests dax/test/dax
optional: true
package for linux amd64:
stage: build
image: golang:$GOVERSION
extends: .go-cache
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
variables:
GOOS: "linux"
GOARCH: "amd64"
script:
- echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | tee /etc/apt/sources.list.d/goreleaser.list
- apt update && apt install nfpm=2.11.3
- make package
artifacts:
paths:
- "*.deb"
- "*.rpm"
upload_artifacts_to_nexus:
stage: post build
image: golang:$GOVERSION
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- curl -v --user "$NEXUS_YUM_CREDS" --upload-file *.arm64.rpm https://nexus.molecula.com/repository/molecula-yum/release/
- curl -v --user "$NEXUS_YUM_CREDS" --upload-file *.amd64.rpm https://nexus.molecula.com/repository/molecula-yum/release/
dependencies:
- package for linux amd64
- package for linux arm64
trigger_m-cloud-images:
stage: post build
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
needs:
- upload_artifacts_to_nexus
trigger: molecula/m-cloud-images
package for linux arm64:
stage: build
image: golang:$GOVERSION
extends: .go-cache
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
variables:
GOOS: "linux"
GOARCH: "arm64"
script:
- echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | tee /etc/apt/sources.list.d/goreleaser.list
- apt update && apt install nfpm=2.11.3
- make package
artifacts:
paths:
- "*.deb"
- "*.rpm"
build arm container fb:
stage: build
needs:
- "build featurebase"
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
before_script:
- echo "${DOCKER_DEPLOY_TOKEN}" | docker login -u ${DOCKER_DEPLOY_USER} --password-stdin ${CI_REGISTRY}
script:
- echo $CI_COMMIT_REF_SLUG
- tag=${CI_REGISTRY_IMAGE}/featurebase:linux-arm64-${CI_COMMIT_REF_SLUG}
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- docker build --build-arg GO_VERSION=$GOVERSION --build-arg ARCH=arm64 --build-arg SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH -t $tag -f .gitlab/Dockerfile .
- docker push $tag
- echo Created docker featurebase image with tag "$tag"
### start idk builds ###
# building them all serially because otherwise you get container name conflicts.
idk build_amd64:
stage: build
variables:
BUILD_NAME: build_${CI_COMMIT_SHA}_${CI_CONCURRENT_ID}
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- cd ./idk/
- date
- make docker-build GOOS="linux" GOARCH="amd64" BUILD_CGO=1
- date
- make docker-build GOOS="darwin" GOARCH="amd64"
- date
artifacts:
paths:
- ./idk/build/*
needs:
# doesn't actually need this... just want it to start executing before *all* the tests finish
- job: run go tests
idk build_arm64:
stage: build
tags:
- shell-arm64
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- cd ./idk/
- date
- make docker-build GOOS="linux" GOARCH="arm64" BUILD_CGO=1 BUILD_NAME="linux-arm64"
- date
- make docker-build GOOS="darwin" GOARCH="arm64"
- date
artifacts:
paths:
- ./idk/build/*
needs:
# doesn't actually need this... just want it to start executing before *all* the tests finish
- job: run go tests
# building them all serially because otherwise you get container name conflicts.
# only do containers on default branch
idk package_docker_all:
stage: build
tags:
- shell
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web")'
script:
- export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
- make docker-idk GOOS="linux" GOARCH="amd64"
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- make docker-idk-tag-push GOOS="linux" GOARCH="amd64"
needs:
- job: idk build_amd64
- job: idk build_arm64
idk s3 dump:
stage: post build
allow_failure: false
variables:
PROFILE: "service-fb-ci"
AWS_SSH_PRIVATE_KEY: $AWS_FBCI_SSH_KEY
AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY
- aws configure set region "us-east-2"
- aws configure set aws_profile $PROFILE
- aws s3 cp ./idk/build/ s3://molecula-artifact-storage/idk/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/ --recursive
- aws s3 cp ./idk/build/ s3://molecula-artifact-storage/idk/${CI_COMMIT_BRANCH}/_latest/ --recursive
needs:
- job: idk build_amd64
- job: idk build_arm64
idk s3 dump tag:
stage: post build
variables:
PROFILE: "service-fb-ci"
AWS_SSH_PRIVATE_KEY: $AWS_FBCI_SSH_KEY
AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY
LOCATION: molecula-artifact-storage/idk/_tags
tags:
- shell
rules:
- if: '$CI_COMMIT_TAG != null && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web")'
script:
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY
- aws configure set region "us-east-2"
- aws configure set aws_profile $PROFILE
- |
for goos in "darwin" "linux"; do
for goarch in "amd64" "arm64"; do
dir=idk-${CI_COMMIT_TAG}-${goos}-${goarch}
echo "Directory ${dir}"
mkdir ${dir}
mv ./idk/build/idk-${goos}-${goarch}/molecula-consumer-* ${dir}/
tar cvzf ${dir}.tar.gz ${dir}
aws s3 cp ${dir} s3://${LOCATION}/${CI_COMMIT_TAG}/${dir}/ --recursive
aws s3 cp ${dir}.tar.gz s3://${LOCATION}/${CI_COMMIT_TAG}/
done
done
needs:
- job: idk build_amd64
- job: idk build_arm64
### end idk builds ###
external lookup tests:
stage: integration
image: golang:$GOVERSION
extends: .go-cache
# TODO: no rules here, do we need to add the rules line?
variables:
POSTGRES_DB: $POSTGRES_DB
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_HOST_AUTH_METHOD: trust
services:
- postgres:13.5
script:
- apt-get update --allow-releaseinfo-change -y
- apt-get install -y postgresql-client
- go test . -run "^TestExternalLookup" -externalLookupDSN postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB?sslmode=disable
s3 dump:
stage: post build
variables:
PROFILE: "service-fb-ci"
AWS_SSH_PRIVATE_KEY: $AWS_FBCI_SSH_KEY
AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web"'
script:
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY
- aws configure set region "us-east-2"
- aws configure set aws_profile $PROFILE
- |
for goos in "darwin" "linux"; do
for goarch in "amd64" "arm64"; do
aws s3 cp featurebase_${goos}_${goarch} s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/featurebase_${goos}_${goarch}
aws s3 cp featurebase_${goos}_${goarch} s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/featurebase_${goos}_${goarch}
aws s3 cp ./build/fbsql_${goos}_${goarch} s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/fbsql_${goos}_${goarch}
aws s3 cp ./build/fbsql_${goos}_${goarch} s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/fbsql_${goos}_${goarch}
done
done
needs:
- job: build featurebase
- job: build fbsql amd64
- job: build fbsql arm64
s3 dump tag:
stage: post build
variables:
PROFILE: "service-fb-ci"
AWS_SSH_PRIVATE_KEY: $AWS_FBCI_SSH_KEY
AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY
LOCATION: molecula-artifact-storage/featurebase/_tags
tags:
- shell
rules:
- if: '$CI_COMMIT_TAG != null && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")'
script:
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY
- aws configure set region "us-east-2"
- aws configure set aws_profile $PROFILE
- |
for goos in "darwin" "linux"; do
for goarch in "amd64" "arm64"; do
dir=featurebase-${CI_COMMIT_TAG}-${goos}-${goarch}
echo "Directory ${dir}"
mkdir $dir
mv featurebase_${goos}_${goarch} ${dir}/featurebase
mv ./build/fbsql_${goos}_${goarch} ${dir}/fbsql
cp NOTICE install/featurebase.conf install/featurebase.*.service ${dir}/
tar cvzf ${dir}.tar.gz ${dir}
aws s3 cp ${dir} s3://${LOCATION}/${CI_COMMIT_TAG}/${dir}/ --recursive
aws s3 cp ${dir}.tar.gz s3://${LOCATION}/${CI_COMMIT_TAG}/
done
done
needs:
- job: build featurebase
- job: build fbsql amd64
- job: build fbsql arm64

24
.gitlab/Dockerfile Normal file
View file

@ -0,0 +1,24 @@
FROM alpine:3.14.2
LABEL maintainer "dev@molecula.com"
LABEL org.opencontainers.image.authors="dev@molecula.com"
ARG ARCH
WORKDIR /
RUN apk add --no-cache curl jq
COPY NOTICE .
COPY featurebase_linux_$ARCH featurebase
RUN chmod ugo+x .
EXPOSE 10101
VOLUME /data
ENV PILOSA_DATA_DIR /data
ENV PILOSA_BIND 0.0.0.0:10101
ENV PILOSA_BIND_GRPC 0.0.0.0:20101
ENTRYPOINT ["/featurebase"]
CMD ["server"]

28
.gitlab/batch-ci.yml Normal file
View file

@ -0,0 +1,28 @@
run go tests batch:
variables:
PROJECT: batch_${CI_CONCURRENT_ID}
# this test relies on stuff that happens after build-lattice, which
# makes it pause the entire CI run waiting for this. we accept the
# small risk of wasting a build against the near certainty of spending
# five minutes running only one job.
stage: nonblocking
retry: 1
script:
- echo "Running test-all"
- cd ./batch/
- echo $PROJECT
- make build-featurebase
- make test-all
after_script:
- cd ./batch/
- make save-featurebase-logs
- make shutdown
artifacts:
paths:
- ./batch/testdata/*_coverage.out
- ./batch/testdata/*_logs.txt
tags:
- shell
- aws
needs:
- job: build amd container fb

83
.golangci.yml Normal file
View file

@ -0,0 +1,83 @@
run:
deadline: 5m
timeout: 5m
skip-dirs-use-default: true
#skip the protobuf generated files
skip-dirs:
- pb
- proto
skip-files:
- pql/pql.peg.go
linters:
enable:
# Recommended to be enabled by default (https://golangci-lint.run).
# - errcheck (lots to fix)
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
# - unused (about 20 to fix)
# Additional linters we choose to enable.
# - bodyclose (lots to fix, but we should)
- errchkjson
- errname
- gofmt
# - misspell (lots to fix, but we should)
- prealloc
# - predeclared (20 to fix)
# - stylecheck (quite a lot to fix, but we should definitely work on this)
- stylecheck
# - unconvert (not at all critical, but makes for cleaner code)
enable-all: false
disable-all: true
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: tab
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
linters-settings:
gofmt:
simplify: true
govet:
# report about shadowed variables
check-shadowing: true
# settings per analyzer
settings:
printf: # analyzer name, run `go tool vet help` to see all analyzers
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
# enable or disable analyzers by name
# run `go tool vet help` to see all analyzers
enable:
- atomicalign
enable-all: false
disable:
- shadow
disable-all: false
stylecheck:
# ST1000: at least one file in a package should have a package comment
# ST1003: golang naming standards
# ST1016: methods on the same type should have the same receiver name
# ST1020: comment on exported function
checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020"]
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0
exclude:
- 'declaration of "(err|ctx)" shadows declaration at'
- 'Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked'

View file

@ -1,28 +0,0 @@
language: go
go:
- 1.8
- 1.9
- master
env:
global: # AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
- secure: "VnBFmFfBOrrf7ONLN9WpAFCcV8SEt5G5VPnnHv97TP7PlJG8LWR6k6O+vRJOvf8V4vDMfKCTDonwWLgbssVf3yygo3C8ZoftY2phehEkWGffCgsd9ML/YBNbGq4LYLSE5HKvBqrZjQaOrVby71BAsP8W7RhC6hqzFQ00M/z8dZVfwaQQFwew2eEcSxLEaaDFS8Wgc3/UuwxDRPBq6u3cCN5RxfB+q70HvGVq4TT+0dqS4eCvz688+Z0GIGYx9olNjh0F2Kc8R2Po0lnUNa0GiHrZ21zeQ1DxIK04QABrWWmjL4h+bx3VHNKPFR4GYSKDf+pj1kfaqbfrAg6rMAJdGejgoS+QyjhgCoN4d3qRp8s+1nrxtp0TvezEdjwyxt4quGHbP5TxWUszssbGhWqf4mx6OeJ8MmdTaJjfu0f3NWJXMycqT6J73WKORk4rHeIqF9CIdxdmcpkwYj8rk0TEMTPTsd7WA8w2HIDsCz/jQnRmEgLUiNnTAofYc/uUi/Wg/T2hllkp+oBDTzxk9NTelkqx8TJ0bDmYYL9JWUi1siFHTHiVYTJgyirSfGNpe61u8OLmT0Hak/D399IfL7qgFLlMXk8q92typfO2xEduq6G+8KygeqiOMSsOY+xcDvZf5xtcEihYd21vjtrxRSqFsup/o8DIxEurQnfXBx1B+WA="
- secure: "U4fpHWDVOG4viqZsiVgUDW7OW1JW60uPOZy0q9pfbs86iHvmZq0PaScsZ+YdlYaN2GETVr7endDf6DCcZs1PWfg0F6VQfkOXcShX8HVS9O58lUZA5tyvbDVql9DQs4PbnkZo+ktz+Z0YaXqq2RdtMDOUz4bgZwspLPMA14if+N6w0tqCFpB7bEtpptTGsdbIQPG1n07yvSeNmK4mvrEEs77tWmhulN5iilpOqhpIvD39bJvtCYVALuJpzLd/OjLTPV9l/fl+hJkMXSj+X5ilO1DHINAcCM648iEX2phXAIWmi0O0Rbg2cI4kV9T5ysOIw8ux+YCm9bZDGTCt+VGBW5Fg+Z5iaXXexyKYCGiHleOJ7kCj9kXxh2u8NiYVNgb19dGJV5/HgQ6pcGWjeVEqr8yY1546zMjpTX+SYGQF+XZe+uggEjeAsk53ueXa0pyZTrlrqSvR7BBtWPx47s/dTg2L19FQYv3XpGMxEXLw92RplExQKi1h7QgihRxFpjGgURHhrt7d9eiNiNqBt3ZsHjmh2AkXZHnaDjlgSnFFWaMqP3UtDBWIuO+2BMbZUJVfP+gpQGBZ4gtpUSmV2JDCHgZgX5OAnLD4usxh+ATQ4rvUXF/tf8nMqEKHlGKd8hxpYSyMX21BoqfSfY4/IA0ejVE9BITqlrvqewqkP1yxe7o="
addons:
before_install:
- go get github.com/mattn/goveralls
script:
- make vendor && $HOME/gopath/bin/goveralls -service=travis-ci -ignore "internal/internal.go,internal/public.pb.go,internal/private.pb.go"
before_deploy:
- pip install awscli --user `whoami`
deploy:
- provider: script
script: make prerelease-upload
skip_cleanup: true
on:
branch: master
matrix:
allow_failures:
- go: master
notifications:
slack:
secure: "SceWannxoGzeSu9PlEhl6icQFGuTmwax870k20nB2ZGYLjo77UEcwYoFwWvFsdYPa/HCo3JorMTYvMJ15VDJcnKEfzDr+kyXbHWBzUumclIOU/Im3ArEN6waQgyGbbWUQhvJjy4ATaxiOlmCyDV+KhKC9P3+WB33/OQtM3ngjAdTXYHAkfEcpeoOP75um+KsQgbi+hlnqfZdgDa6yIkFjaS3KZEJW1vmcOYYzNsXOA1Ip8j1NY6AjjWZlQorZJ/SYFqdhIv8ST3+a6cQk12u3t6TwZdcr3wmm1qmiW/SaK7UesWlT/YfElIuK8BBq9w1oZHxNKoAmLWTOe7MMisdItmtwgA14eMGl1rvNFlVf9sjsxs4AAzFvSZBZdDfx9XeLCBU5I2WUc/PKUgNQBPMVChxA7gEhtZLndsDdye7LsZASD2yYqjlVlgoZpzRexee/cJgCqUcNKDBHF39ZJYxV4KtZ0prjcSnVmLvuapplzTV4LZ+LyFapCyhiuM/oMJvxgmd7jTtFb5e5EkaHBPN1XwQWZw87yCjKsunTlTe1f1a5qoH/xvJHNpqE/jxOHU3DTLDgTxhb+FwC1Qj9a8bp+UYLw5F4P46ZnHlBGc2O74klv17EqvUMn3JhzASUtyxLGOgJulJ+o83rxJvhSiWt3GQIfkExVPzmz11641ElJI="

View file

@ -1,213 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.8.0] - 2017-11-15
This version contains 31 contributions from 8 contributors. There are 84 files changed, 3,732 insertions, and 1,428 deletions.
### Added
- Diagnostics ([#895](https://github.com/pilosa/pilosa/pull/895))
- Add docker-build make target for repeatable Docker-based builds ([#933](https://github.com/pilosa/pilosa/pull/933))
- Add documentation on importing field values; fixes #924 ([#938](https://github.com/pilosa/pilosa/pull/938))
- Add flag documentation and tests, remove "plugins.path" ([#942](https://github.com/pilosa/pilosa/pull/942))
- Add TLS support ([#867](https://github.com/pilosa/pilosa/pull/867))
- Add TLS cluster how to ([#898](https://github.com/pilosa/pilosa/pull/898))
- Add support for gossip encryption ([#889](https://github.com/pilosa/pilosa/pull/889))
- Add Recalculate Caches endpoint ([#881](https://github.com/pilosa/pilosa/pull/881))
- Add search-friendly documentation for BSI range query syntax ([#955](https://github.com/pilosa/pilosa/pull/955))
### Changed
- Remove unneeded Gopkg.toml constraints and update all dependencies ([#943](https://github.com/pilosa/pilosa/pull/943))
- Remove row and column labels in webUI ([#884](https://github.com/pilosa/pilosa/pull/884))
- Internal Client refactoring ([#892](https://github.com/pilosa/pilosa/pull/892))
- Remove column/row labels for input definition ([#945](https://github.com/pilosa/pilosa/pull/945))
- Update dependencies and Go version ([#878](https://github.com/pilosa/pilosa/pull/878))
### Fixed
- Skip permissions test when run as root. Fixes #940 ([#941](https://github.com/pilosa/pilosa/pull/941))
- Address "connection reset" issues in client ([#934](https://github.com/pilosa/pilosa/pull/934))
- Fix field value import: Use signed int and respect field minimum ([#919](https://github.com/pilosa/pilosa/pull/919))
- Constrain BoltDB to version rather than specific revision ([#887](https://github.com/pilosa/pilosa/pull/887))
- Fix bug in environment variable format ([#882](https://github.com/pilosa/pilosa/pull/882))
- Fix overflow in differenceRunBitmap ([#949](https://github.com/pilosa/pilosa/pull/949))
### Performance
- Use FieldNotNull to improve efficiency of BETWEEN queries ([#874](https://github.com/pilosa/pilosa/pull/874))
## [0.7.2] - 2017-11-15
This version contains 1 contribution from 1 contributor. There is 1 file changed, 16 insertions, and 1 deletion.
### Changed
- Bump HTTP client's MaxIdleConns and MaxIdleConnsPerHost ([#920](https://github.com/pilosa/pilosa/pull/920))
## [0.7.1] - 2017-10-09
This version contains 3 contributions from 3 contributors. There are 14 files changed, 221 insertions, and 52 deletions.
### Changed
- Update dependencies and Go version ([#878](https://github.com/pilosa/pilosa/pull/878))
### Performance
- Leverage not-null field to make BETWEEN queries more efficient ([#874](https://github.com/pilosa/pilosa/pull/874))
## [0.7.0] - 2017-10-03
This version contains 59 contributions from 9 contributors. There are 61 files changed, 5207 insertions, and 1054 deletions.
### Added
- Add HTTP API for fields ([#811](https://github.com/pilosa/pilosa/pull/811), [#856](https://github.com/pilosa/pilosa/pull/856))
- Add HTTP API for delete views ([#785](https://github.com/pilosa/pilosa/pull/785))
- Modify import endpoint to handle BSI field values ([#840](https://github.com/pilosa/pilosa/pull/840))
- Add field Range() support to Executor ([#791](https://github.com/pilosa/pilosa/pull/791))
- Support PQL Range() queries for fields ([#755](https://github.com/pilosa/pilosa/pull/755))
- Add Sum() field query ([#778](https://github.com/pilosa/pilosa/pull/778))
- Add documentation for BSI ([#861](https://github.com/pilosa/pilosa/pull/861))
- Add BETWEEN for Range queries ([#847](https://github.com/pilosa/pilosa/pull/847))
- Add Xor support for PQL ([#789](https://github.com/pilosa/pilosa/pull/789))
- Enable auto-creating the schema on imports ([#837](https://github.com/pilosa/pilosa/pull/837))
- Update client library docs ([#831](https://github.com/pilosa/pilosa/pull/831))
- Handle SIGTERM signal ([#830](https://github.com/pilosa/pilosa/pull/830))
- Add cluster config example to docs ([#806](https://github.com/pilosa/pilosa/pull/806))
- Add ability to exclude attributes and bits in Bitmap queries ([#783](https://github.com/pilosa/pilosa/pull/783))
### Fixed
- Fix panic when iterating over an empty run container ([#860](https://github.com/pilosa/pilosa/pull/860))
- Fix row id zero bug ([#814](https://github.com/pilosa/pilosa/pull/814))
- Fix cache invalidation bug ([#795](https://github.com/pilosa/pilosa/pull/795))
- Set container.n in differenceRunRun ([#794](https://github.com/pilosa/pilosa/pull/794))
- Fix infinite loop in bitmap-to-array conversion ([#779](https://github.com/pilosa/pilosa/pull/779))
- Fix CountRange bug ([#773](https://github.com/pilosa/pilosa/pull/773))
### Deprecated
- Remove support for row/column labels ([#839](https://github.com/pilosa/pilosa/pull/839))
### Performance
- Refactor differenceRunArray ([#859](https://github.com/pilosa/pilosa/pull/859))
- Update fragment.FieldSum to use roaring IntersectionCount() ([#841](https://github.com/pilosa/pilosa/pull/841))
- Add roaring optimizations ([#842](https://github.com/pilosa/pilosa/pull/842))
- Convert lock to read lock ([#848](https://github.com/pilosa/pilosa/pull/848))
- Reduce Lock calls in executor ([#846](https://github.com/pilosa/pilosa/pull/846))
- Implement container.flipBitmap() to improve differenceRunBitmap() ([#849](https://github.com/pilosa/pilosa/pull/849))
- Reuse container storage on UnmarshalBinary to improve memory utilization ([#820](https://github.com/pilosa/pilosa/pull/820))
- Improve WriteTo performance ([#812](https://github.com/pilosa/pilosa/pull/812))
## [0.6.0] - 2017-08-11
This version contains 14 contributions from 5 contributors. There are 28 files changed, 4,936 insertions, and 692 deletions.
### Added
- Add Run-length Encoding ([#758](https://github.com/pilosa/pilosa/pull/758))
### Changed
- Make gossip the default broadcast type ([#750](https://github.com/pilosa/pilosa/pull/750))
### Fixed
- Fix CountRange ([#759](https://github.com/pilosa/pilosa/pull/759))
- Fix `differenceArrayRun` logic ([#674](https://github.com/pilosa/pilosa/pull/674))
## [0.5.0] - 2017-08-02
This version contains 65 contributions from 8 contributors (including 1 volunteer contributor). There are 79 files changed, 7,972 insertions, and 2,800 deletions.
### Added
- Set open file limit during Pilosa startup ([#748](https://github.com/pilosa/pilosa/pull/748))
- Add Input Definition ([#646](https://github.com/pilosa/pilosa/pull/646))
- Add cache type: None ([#745](https://github.com/pilosa/pilosa/pull/745))
- Add panic recovery in top level HTTP handler ([#741](https://github.com/pilosa/pilosa/pull/741))
- Count open file handles as a StatsD metric ([#636](https://github.com/pilosa/pilosa/pull/636))
- Add coverage tools to Makefile ([#635](https://github.com/pilosa/pilosa/pull/635))
- Add Holder test coverage ([#629](https://github.com/pilosa/pilosa/pull/629))
- Add runtime memory metrics ([#600](https://github.com/pilosa/pilosa/pull/600))
- Add sorting flag to import command ([#606](https://github.com/pilosa/pilosa/pull/606))
- Add PQL support for field values (WIP) ([#721](https://github.com/pilosa/pilosa/pull/721))
- Set and retrieve field values (WIP) ([#702](https://github.com/pilosa/pilosa/pull/702))
- Add BSI range-encoding schema support (WIP) ([#670](https://github.com/pilosa/pilosa/pull/670))
### Changed
- Move InternalPort config option to top-level ([#747](https://github.com/pilosa/pilosa/pull/747))
- Switch from glide to dep for dependency management ([#744](https://github.com/pilosa/pilosa/pull/744))
- Remove QueryRequest.Quantum since it is no longer used ([#699](https://github.com/pilosa/pilosa/pull/699))
- Refactor test utilities into importable package ([#675](https://github.com/pilosa/pilosa/pull/675))
### Fixed
- Add mutex for attribute cache ([#729](https://github.com/pilosa/pilosa/pull/729))
- Use log-path flag to specify log file ([#678](https://github.com/pilosa/pilosa/pull/678))
## [0.4.0] - 2017-06-08
This version contains 53 contributions from 13 contributors (including 4 volunteer contributors). There are 96 files changed, 6373 insertions, and 770 deletions.
*Note that data files created in Pilosa < 0.4.0 are not compatible with Pilosa 0.4.0 as a result of [#520](https://github.com/pilosa/pilosa/pull/520).*
### Added
- Support metric reporting through StatsD protocol ([#468](https://github.com/pilosa/pilosa/pull/468), [#568](https://github.com/pilosa/pilosa/pull/568), [#580](https://github.com/pilosa/pilosa/pull/580))
- Improve test coverage for ctl package ([#586](https://github.com/pilosa/pilosa/pull/586))
- Add support for bit flip (negate) in roaring ([#592](https://github.com/pilosa/pilosa/pull/592))
- Add xor support to roaring ([#571](https://github.com/pilosa/pilosa/pull/571))
- Improve WebUI autocomplete ([#560](https://github.com/pilosa/pilosa/pull/560))
- Add syntax hints tooltip to WebUI ([#537](https://github.com/pilosa/pilosa/pull/537))
- Implement 'config' CLI command ([#541](https://github.com/pilosa/pilosa/pull/541))
- Move docs into repo ([#563](https://github.com/pilosa/pilosa/pull/563))
- Add inverse TopN() support ([#551](https://github.com/pilosa/pilosa/pull/551))
- Add various Makefile updates ([#540](https://github.com/pilosa/pilosa/pull/540))
- Provide details on Glide checksum mismatch ([#546](https://github.com/pilosa/pilosa/pull/546))
- Add Docker multi-stage build ([#535](https://github.com/pilosa/pilosa/pull/535))
- Support inverse Range() queries ([#533](https://github.com/pilosa/pilosa/pull/533))
- Support colon commands in WebUI ([#529](https://github.com/pilosa/pilosa/pull/529), [#510](https://github.com/pilosa/pilosa/pull/510))
### Changed
- Increase default partition count from 16 to 256 (BREAKING CHANGE) ([#520](https://github.com/pilosa/pilosa/pull/520))
- Validate unknown query params ([#578](https://github.com/pilosa/pilosa/pull/578))
- Validate configuration file ([#573](https://github.com/pilosa/pilosa/pull/573))
- Change default cache type to ranked ([#524](https://github.com/pilosa/pilosa/pull/524))
- Add max-writes-per-requests limit ([#525](https://github.com/pilosa/pilosa/pull/525))
### Fixed
- Add "make test" to PHONY section of Makefile ([#605](https://github.com/pilosa/pilosa/pull/605))
- Fix failing tests when IPv6 is disabled ([#594](https://github.com/pilosa/pilosa/pull/594))
- Add minor docs fix, indent in JSON ([#599](https://github.com/pilosa/pilosa/pull/599))
- Fix BroadcastHandler handle missing index error ([#597](https://github.com/pilosa/pilosa/pull/597))
- Add WebUI fixes ([#589](https://github.com/pilosa/pilosa/pull/589))
- Fix support for 32-bit Linux ([#549](https://github.com/pilosa/pilosa/pull/549), [#565](https://github.com/pilosa/pilosa/pull/565))
- Fix 3 separate bugs in bitmapCountRange ([#559](https://github.com/pilosa/pilosa/pull/559))
- Add client support for MaxInverseSliceByIndex ([#555](https://github.com/pilosa/pilosa/pull/555))
- Fix bug in `handleGetSliceMax` ([#554](https://github.com/pilosa/pilosa/pull/554))
- Default to `standard` view in export command ([#548](https://github.com/pilosa/pilosa/pull/548))
- Fix vet issues with the assembly code in Roaring ([#528](https://github.com/pilosa/pilosa/pull/528))
- Prevent row labels that match the column label ([#503](https://github.com/pilosa/pilosa/pull/503))
- Fix roaring test: TestBitmap_Quick_Array1 ([#507](https://github.com/pilosa/pilosa/pull/507))
- Don't try to create inverse views on Import() when inverseEnabled is false ([#462](https://github.com/pilosa/pilosa/pull/462))
### Performance
- Set n based on array length instead of incrementing repeatedly ([#590](https://github.com/pilosa/pilosa/pull/590))
- Rewrite intersectCountArrayBitmap for perf test ([#577](https://github.com/pilosa/pilosa/pull/577))
- Check for duplicate attributes under read lock on insert ([#562](https://github.com/pilosa/pilosa/pull/562))
[Unreleased]: https://github.com/pilosa/pilosa/compare/v0.5...HEAD
[0.4.0]: https://github.com/pilosa/pilosa/compare/v0.3...v0.4
[0.5.0]: https://github.com/pilosa/pilosa/compare/v0.4...v0.5
[0.6.0]: https://github.com/pilosa/pilosa/compare/v0.5...v0.6
[0.7.0]: https://github.com/pilosa/pilosa/compare/v0.6...v0.7
[0.8.0]: https://github.com/pilosa/pilosa/compare/v0.7...v0.8

133
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
community@featurebase.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View file

@ -1,62 +0,0 @@
# Contributing to Pilosa
## Reporting a bug
If you have discovered a bug and don't see it in the [github issue tracker][5], [open a new issue][1]
## Submitting a feature request
Feature requests are managed in Github issues. New features typically go through a [Proposal Process][4]
which starts by [opening a new issue][1] that describes the new feature proposal.
## Submitting code changes
Before you start working on new features, you should [open a new issue][1] to let others know what
you're doing before you start working, otherwise you run the risk of duplicating effort. This also
gives others an opportunity to provide input for your feature.
If you want to help but you aren't sure where to start, check out our [github label for low-effort issues][6].
- Fork the [Pilosa repository][2] and then clone your fork:
```shell
git clone git@github.com:<your-name>/pilosa.git
```
- Create a local feature branch:
```shell
git checkout -b something-amazing
```
- Commit your changes locally using `git add` and `git commit`.
- Make sure that you've written tests for your new feature, and then run the tests:
```shell
make test
```
- Verify that your pull request is applied to the latest version of code on github:
```shell
git remote add upstream git@github.com:pilosa/pilosa.git
git fetch upstream
git rebase -i upstream/master
```
- Push to your fork:
```shell
git push -u <yourfork> something-amazing
```
- Submit a [pull request][3]
[1]: https://github.com/pilosa/pilosa/issues/new
[2]: https://github.com/pilosa/pilosa
[3]: https://github.com/pilosa/pilosa/compare/
[4]: https://github.com/pilosa/general/blob/master/proposal.md
[5]: https://github.com/pilosa/pilosa/issues
[6]: https://github.com/pilosa/pilosa/issues?q=is%3Aopen+is%3Aissue+label%3Anewcomer

View file

@ -1,21 +1,58 @@
FROM golang:1.9.2 as builder
ARG GO_VERSION=latest
ARG ldflags=''
#######################
### Lattice builder ###
#######################
COPY . /go/src/github.com/pilosa/pilosa
FROM ghcr.io/featurebasedb/nodejs:0.0.1 as lattice-builder
WORKDIR /lattice
RUN cd /go/src/github.com/pilosa/pilosa \
&& make vendor \
&& CGO_ENABLED=0 go install -a -ldflags "$ldflags" github.com/pilosa/pilosa/cmd/pilosa
COPY lattice/package.json ./
COPY lattice/yarn.lock ./
RUN yarn install
FROM scratch
COPY lattice ./
RUN yarn build
LABEL maintainer "dev@pilosa.com"
######################
### Pilosa builder ###
######################
COPY --from=builder /go/bin/pilosa /pilosa
FROM golang:${GO_VERSION} as pilosa-builder
ARG MAKE_FLAGS
ARG SOURCE_DATE_EPOCH
WORKDIR /pilosa
RUN go install github.com/rakyll/statik@v0.1.7
COPY . ./
COPY --from=lattice-builder /lattice/build /lattice
RUN /go/bin/statik -src=/lattice -dest=/pilosa
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
RUN make build FLAGS="-o build/featurebase" ${MAKE_FLAGS}
#####################
### Pilosa runner ###
#####################
FROM alpine:3.13.2 as runner
LABEL maintainer "dev@molecula.com"
RUN apk add --no-cache curl jq tree
COPY --from=pilosa-builder /pilosa/build/featurebase /
COPY NOTICE /NOTICE
EXPOSE 10101
VOLUME /data
ENTRYPOINT ["/pilosa"]
CMD ["server", "--data-dir", "/data", "--bind", "http://0.0.0.0:10101"]
ENV PILOSA_DATA_DIR /data
ENV PILOSA_BIND 0.0.0.0:10101
ENV PILOSA_BIND_GRPC 0.0.0.0:20101
ENTRYPOINT ["/featurebase"]
CMD ["server"]

38
Dockerfile-clustertests Normal file
View file

@ -0,0 +1,38 @@
# This Dockerfile is used for cluster testing - it produces a much larger image
# and includes all of Go as well as some utilities.
FROM golang:1.19
LABEL maintainer "dev@pilosa.com"
COPY . /go/src/github.com/featurebasedb/featurebase/
# download pumba for fault injection
ADD https://github.com/alexei-led/pumba/releases/download/0.6.0/pumba_linux_amd64 /pumba
RUN chmod +x /pumba
# add docker client to pause/unpause nodes
RUN apt update
RUN apt install -y docker.io
# add docker-compose so tests can use it for stuff
ADD https://github.com/docker/compose/releases/latest/download/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose
WORKDIR /go/src/github.com/featurebasedb/featurebase/cmd/featurebase
# generate an instrumented binary to allow for calculating code coverage for clustertests
# the entrypoint for the binary is TestRunMain, which is wrapper for main
RUN go test -covermode=atomic -coverpkg=../../... -c -tags testrunmain -o featurebase
RUN cp /go/src/github.com/featurebasedb/featurebase/cmd/featurebase/featurebase /featurebase
COPY NOTICE /NOTICE
EXPOSE 10101
VOLUME /data
# use e.g. "-test.coverprofile=/results/coverage.out"
CMD ["/featurebase", "-test.run=TestRunMain", "server"]

View file

@ -0,0 +1,37 @@
# This Dockerfile is used for cluster testing - it produces a much larger image
# and includes all of Go as well as some utilities.
FROM golang:1.19
LABEL maintainer "dev@pilosa.com"
COPY . /go/src/github.com/featurebasedb/featurebase/
# download pumba for fault injection
ADD https://github.com/alexei-led/pumba/releases/download/0.6.0/pumba_linux_amd64 /pumba
RUN chmod +x /pumba
# add docker client to pause/unpause nodes
RUN apt update
RUN apt install -y docker.io
# add docker-compose so tests can use it for stuff
ADD https://github.com/docker/compose/releases/latest/download/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose
WORKDIR /go/src/github.com/featurebasedb/featurebase/cmd/featurebase
RUN go test -covermode=atomic -coverpkg=../../... -c -tags testrunmain -o featurebase
RUN cp /go/src/github.com/featurebasedb/featurebase/cmd/featurebase/featurebase /featurebase
COPY NOTICE /NOTICE
COPY ./internal/clustertests /go/src/github.com/featurebasedb/featurebase/internal/clustertests
EXPOSE 10101
VOLUME /data
WORKDIR /go/src/github.com/featurebasedb/featurebase
CMD ["/featurebase", "-test.run=TestRunMain", "-test.coverprofile=/results/coverage.out", "server", "--data-dir", "/data", "--bind", "http://0.0.0.0:10101"]

47
Dockerfile-datagen Normal file
View file

@ -0,0 +1,47 @@
# syntax=docker/dockerfile:1
##########################
### datagen builder ###
##########################
FROM golang:alpine as builder
WORKDIR /featurebase
COPY . ./
RUN apk add --no-cache build-base bash git make librdkafka pkgconfig
# install librdkafka
RUN git clone https://github.com/edenhill/librdkafka.git
RUN cd librdkafka && ./configure --prefix /usr && make && make install
ENV PKG_CONFIG_PATH=/usr/lib/pkgconfig/
RUN cd idk && make build-datagen
# ENTRYPOINT ["tail", "-f", "/dev/null"]
#########################
### datagen runner ###
#########################
FROM alpine:3.15.3 as runner
WORKDIR /
LABEL maintainer "dev@molecula.com"
RUN apk add --no-cache curl jq
COPY --from=builder /featurebase/idk/build/datagen /bin/
COPY --from=builder /usr/lib/librdkafka* /usr/lib/
COPY idk/datagen/testdata/* /testdata/
EXPOSE 8080
# VOLUME /data
# ENV ADDR 0.0.0.0:8080
#ENTRYPOINT ["sleep", "infinity"]
ENTRYPOINT ["datagen"]

32
Dockerfile-dax Normal file
View file

@ -0,0 +1,32 @@
ARG GO_VERSION=latest
###########################
### FeatureBase Builder ###
###########################
FROM golang:${GO_VERSION} as featurebase-builder
ARG MAKE_FLAGS
WORKDIR /fb
COPY . ./
RUN make build FLAGS="-o build/featurebase" ${MAKE_FLAGS}
##########################
### FeatureBase runner ###
##########################
FROM golang:alpine as runner
LABEL maintainer "dev@featurebase.com"
RUN apk add --no-cache curl jq tree
COPY --from=featurebase-builder /fb/build/featurebase /
COPY NOTICE /NOTICE
EXPOSE 8080
ENTRYPOINT ["/featurebase"]
CMD ["dax"]

18
Dockerfile-dax-quick Normal file
View file

@ -0,0 +1,18 @@
ARG GO_VERSION=latest
##########################
### FeatureBase runner ###
##########################
FROM alpine:3.13.2 as runner
LABEL maintainer "dev@featurebase.com"
RUN apk add --no-cache curl jq tree
COPY ./fb_linux /featurebase
EXPOSE 8080
ENTRYPOINT ["/featurebase"]
CMD ["dax"]

48
Dockerfile-fbsql Normal file
View file

@ -0,0 +1,48 @@
ARG GO_VERSION=1.19
FROM golang:1.19-buster as builder
WORKDIR /
RUN apt-get update -y -qq && apt-get install -y -qq \
build-essential \
git \
musl-tools \
netcat \
unixodbc \
unixodbc-dev \
&& rm -rf /var/lib/apt/lists/*
RUN ["git", "clone", "https://github.com/edenhill/librdkafka.git"]
WORKDIR /librdkafka
RUN ./configure --prefix /usr && \
make && \
make install
WORKDIR /featurebase
COPY . .
ARG MAKE_FLAGS
ARG GO_BUILD_FLAGS
ARG SOURCE_DATE_EPOCH
WORKDIR /featurebase/
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
RUN make build-fbsql GO_BUILD_FLAGS="-mod=vendor ${GO_BUILD_FLAGS}" ${MAKE_FLAGS}
FROM ubuntu:20.04 as runner
RUN apt-get update -y -qq && apt-get install -y -qq \
ca-certificates \
musl-tools \
netcat \
unixodbc-dev \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /featurebase/fbsql /usr/local/bin/
# Verify that the linker can find everything.
FROM runner as linkcheck
RUN if [ -e /usr/local/bin/fbsql ] ; then ldd /usr/local/bin/fbsql; fi
FROM runner

243
Gopkg.lock generated
View file

@ -1,243 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/BurntSushi/toml"
packages = ["."]
revision = "b26d9c308763d68093482582cea63d69be07a0f0"
version = "v0.3.0"
[[projects]]
branch = "master"
name = "github.com/CAFxX/gcnotifier"
packages = ["."]
revision = "39b0596a2da3c92787b3319c6b5425a474b4e0da"
[[projects]]
name = "github.com/DataDog/datadog-go"
packages = ["statsd"]
revision = "0ddda6bee21174ef6c4873647cb0d6ec9cba996f"
version = "1.1.0"
[[projects]]
branch = "master"
name = "github.com/armon/go-metrics"
packages = ["."]
revision = "9a4b6e10bed6220a1665955aa2b75afc91eb10b3"
[[projects]]
name = "github.com/boltdb/bolt"
packages = ["."]
revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8"
version = "v1.3.1"
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
name = "github.com/fsnotify/fsnotify"
packages = ["."]
revision = "629574ca2a5df945712d3079857300b5e4da0236"
version = "v1.4.2"
[[projects]]
name = "github.com/gogo/protobuf"
packages = ["proto"]
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
version = "v0.5"
[[projects]]
branch = "master"
name = "github.com/golang/groupcache"
packages = ["lru"]
revision = "84a468cf14b4376def5d68c722b139b881c450a4"
[[projects]]
branch = "master"
name = "github.com/golang/protobuf"
packages = ["proto"]
revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
[[projects]]
name = "github.com/gorilla/context"
packages = ["."]
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
version = "v1.1"
[[projects]]
name = "github.com/gorilla/mux"
packages = ["."]
revision = "7f08801859139f86dfafd1c296e2cba9a80d292e"
version = "v1.6.0"
[[projects]]
branch = "master"
name = "github.com/hashicorp/errwrap"
packages = ["."]
revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55"
[[projects]]
branch = "master"
name = "github.com/hashicorp/go-immutable-radix"
packages = ["."]
revision = "8aac2701530899b64bdea735a1de8da899815220"
[[projects]]
branch = "master"
name = "github.com/hashicorp/go-msgpack"
packages = ["codec"]
revision = "fa3f63826f7c23912c15263591e65d54d080b458"
[[projects]]
branch = "master"
name = "github.com/hashicorp/go-multierror"
packages = ["."]
revision = "83588e72410abfbe4df460eeb6f30841ae47d4c4"
[[projects]]
branch = "master"
name = "github.com/hashicorp/go-sockaddr"
packages = ["."]
revision = "9b4c5fa5b10a683339a270d664474b9f4aee62fc"
[[projects]]
branch = "master"
name = "github.com/hashicorp/golang-lru"
packages = ["simplelru"]
revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6"
[[projects]]
branch = "master"
name = "github.com/hashicorp/hcl"
packages = [".","hcl/ast","hcl/parser","hcl/scanner","hcl/strconv","hcl/token","json/parser","json/scanner","json/token"]
revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8"
[[projects]]
name = "github.com/hashicorp/memberlist"
packages = ["."]
revision = "ce8abaa0c60c2d6bee7219f5ddf500e0a1457b28"
version = "v0.1.0"
[[projects]]
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
name = "github.com/magiconair/properties"
packages = ["."]
revision = "be5ece7dd465ab0765a9682137865547526d1dfb"
version = "v1.7.3"
[[projects]]
branch = "master"
name = "github.com/miekg/dns"
packages = [".","internal/socket"]
revision = "9fc4eb252eedf0ef8adc05169ce35da5e31beaba"
[[projects]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
revision = "06020f85339e21b2478f756a78e295255ffa4d6a"
[[projects]]
name = "github.com/pelletier/go-toml"
packages = ["."]
revision = "16398bac157da96aa88f98a2df640c7f32af1da2"
version = "v1.0.1"
[[projects]]
name = "github.com/rakyll/statik"
packages = ["fs"]
revision = "fd36b3595eb2ec8da4b8153b107f7ea08504899d"
version = "v0.1.1"
[[projects]]
branch = "master"
name = "github.com/sean-/seed"
packages = ["."]
revision = "e2103e2c35297fb7e17febb81e49b312087a2372"
[[projects]]
name = "github.com/sony/gobreaker"
packages = ["."]
revision = "e9556a45379ef1da12e54847edb2fb3d7d566f36"
version = "0.3.0"
[[projects]]
branch = "master"
name = "github.com/spf13/afero"
packages = [".","mem"]
revision = "5660eeed305fe5f69c8fc6cf899132a459a97064"
[[projects]]
name = "github.com/spf13/cast"
packages = ["."]
revision = "acbeb36b902d72a7a4c18e8f3241075e7ab763e4"
version = "v1.1.0"
[[projects]]
name = "github.com/spf13/cobra"
packages = ["."]
revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b"
version = "v0.0.1"
[[projects]]
branch = "master"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
revision = "12bd96e66386c1960ab0f74ced1362f66f552f7b"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
version = "v1.0.0"
[[projects]]
name = "github.com/spf13/viper"
packages = ["."]
revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7"
version = "v1.0.0"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context"]
revision = "a337091b0525af65de94df2eb7e98bd9962dcbe2"
[[projects]]
branch = "master"
name = "golang.org/x/sync"
packages = ["errgroup"]
revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "1e2299c37cc91a509f1b12369872d27be0ce98a6"
[[projects]]
branch = "master"
name = "golang.org/x/text"
packages = ["internal/gen","internal/triegen","internal/ucd","transform","unicode/cldr","unicode/norm"]
revision = "88f656faf3f37f690df1a32515b479415e1a6769"
[[projects]]
branch = "v2"
name = "gopkg.in/yaml.v2"
packages = ["."]
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "75badb0bcc3bb356b04af17979e0af61b4b66c5e0a483f09e39cf1f9b5e5de2c"
solver-name = "gps-cdcl"
solver-version = 1

View file

@ -1,3 +0,0 @@
# This file intentionally left blank as all needed dependencies are imported by
# the project and thus tracked by `dep`.
# See https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md for details.

View file

@ -1,4 +1,3 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@ -187,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2023 Molecula Corp. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

476
Makefile
View file

@ -1,115 +1,405 @@
.PHONY: dep docker pilosa release-build prerelease-build release prerelease prerelease-upload install generate statik test cover cover-pkg cover-viz clean docker-build docker-test
.PHONY: build clean build-lattice cover cover-viz default docker docker-build docker-build-fbsql docker-tag-push generate generate-protoc generate-pql generate-statik generate-stringer install install-protoc-gen-gofast install-protoc install-statik install-peg test docker-login
DEP := $(shell command -v dep 2>/dev/null)
STATIK := $(shell command -v statik 2>/dev/null)
PROTOC := $(shell command -v protoc 2>/dev/null)
SHELL := /bin/bash
VERSION := $(shell git describe --tags 2> /dev/null || echo unknown)
IDENTIFIER := $(VERSION)-$(GOOS)-$(GOARCH)
CLONE_URL=github.com/pilosa/pilosa
PKGS := $(shell cd $(GOPATH)/src/$(CLONE_URL); go list ./... | grep -v vendor)
BUILD_TIME=`date -u +%FT%T%z`
LDFLAGS="-X github.com/pilosa/pilosa.Version=$(VERSION) -X github.com/pilosa/pilosa.BuildTime=$(BUILD_TIME)"
DOCKER_GOLANG_IMAGE=golang:latest
VARIANT = Molecula
GO=go
GOOS=$(shell $(GO) env GOOS)
GOARCH=$(shell $(GO) env GOARCH)
VERSION_ID=$(if $(TRIAL_DEADLINE),trial-$(TRIAL_DEADLINE)-,)$(VERSION)-$(GOOS)-$(GOARCH)
DATE_FMT="+%FT%T%z"
# set SOURCE_DATE_EPOCH like this to use the last git commit timestamp
# export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) instead of the current time from running `date`
ifdef SOURCE_DATE_EPOCH
BUILD_TIME ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u "$(DATE_FMT)")
else
BUILD_TIME ?= $(shell date -u "$(DATE_FMT)")
endif
SHARD_WIDTH = 20
COMMIT := $(shell git describe --exact-match >/dev/null 2>&1 || git rev-parse --short HEAD)
LDFLAGS="-X github.com/featurebasedb/featurebase/v3.Version=$(VERSION) -X github.com/featurebasedb/featurebase/v3.BuildTime=$(BUILD_TIME) -X github.com/featurebasedb/featurebase/v3.Variant=$(VARIANT) -X github.com/featurebasedb/featurebase/v3.Commit=$(COMMIT) -X github.com/featurebasedb/featurebase/v3.TrialDeadline=$(TRIAL_DEADLINE)"
GO_VERSION=1.19
GO_BUILD_FLAGS=
DOCKER_BUILD= # set to 1 to use `docker-build` instead of `build` when creating a release
BUILD_TAGS +=
TEST_TAGS = roaringparanoia
TEST_TIMEOUT=10m
RACE_TEST_TIMEOUT=10m
# size in GB to use for ramdisk, ?= so you can override it with env
# 4GB is not enough for `make test`, 8GB usually is.
RAMDISK_SIZE ?= 8
default: test pilosa
export GO111MODULE=on
export GOPRIVATE=github.com/molecula
export CGO_ENABLED=0
AWS_ACCOUNTID ?= undefined
# Run tests and compile Pilosa
default: test build
# Remove build directories
clean:
rm -rf vendor build
rm -f *.rpm *.deb
$(GOPATH)/bin:
mkdir $(GOPATH)/bin
# Set up vendor directory using `go mod vendor`
vendor: go.mod
$(GO) mod vendor
dep: $(GOPATH)/bin
go get -u github.com/golang/dep/cmd/dep
version:
@echo $(VERSION)
vendor: Gopkg.toml
ifndef DEP
make dep
endif
dep ensure
touch vendor
# We build a list of packages that omits the IDK and batch packages because
# those packages require fancy environment setup.
GOPACKAGES := $(shell $(GO) list ./... | grep -v "/v3/idk" | grep -v "/v3/batch")
Gopkg.lock: dep Gopkg.toml
dep ensure
# Run test suite
test:
$(GO) test $(GOPACKAGES) -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -timeout $(TEST_TIMEOUT) -count=1
test: vendor
go test $(PKGS) $(TESTFLAGS)
# Run test suite with race flag
test-race:
CGO_ENABLED=1 $(GO) test $(GOPACKAGES) -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -race -timeout $(RACE_TEST_TIMEOUT) -v
cover: vendor
mkdir -p build/coverage
echo "mode: set" > build/coverage/all.out
for pkg in $(PKGS) ; do \
make cover-pkg PKG=$$pkg ; \
done
testv: testvsub
cover-pkg:
mkdir -p build/coverage
touch build/coverage/$(subst /,-,$(PKG)).out
go test -coverprofile=build/coverage/$(subst /,-,$(PKG)).out $(PKG)
tail -n +2 build/coverage/$(subst /,-,$(PKG)).out >> build/coverage/all.out
testv-race: testvsub-race
# testvsub: run go test -v in sub-directories in "local mode" with incremental output,
# avoiding go -test ./... "package list mode" which doesn't give output
# until the test run finishes. Package list mode makes it hard to
# find which test is hung/deadlocked.
#
testvsub:
@set -e; for pkg in $(GOPACKAGES); do \
if [ $${pkg:0:38} == "github.com/featurebasedb/featurebase/v3/idk" ]; then \
echo; echo "___ skipping subpkg $$pkg"; \
continue; \
fi; \
echo; echo "___ testing subpkg $$pkg"; \
$(GO) test -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -timeout $(RACE_TEST_TIMEOUT) $$pkg || break; \
echo; echo "999 done testing subpkg $$pkg"; \
done
# make a $(RAMDISK_SIZE)GB RAMDisk. Speed up tests by running
# them with TMPDIR=/mnt/ramdisk.
ramdisk-linux:
mount -o size=$(RAMDISK__SIZE)G -t tmpfs none /mnt/ramdisk
# make a $(RAMDISK_SIZE)GB RAMDisk. Speed up tests by running
# them with TMPDIR=/Volumes/RAMDisk. This is more important on
# OS X than it is on Linux, because there's performance issues
# with fsync on OS X that can make the SSD slow down to moving-platters
# drive speeds. Oops.
ramdisk-osx:
diskutil erasevolume HFS+ 'RAMDisk' $$(hdiutil attach -nobrowse -nomount ram://$$(expr 2097152 \* $(RAMDISK_SIZE)))
detach-ramdisk-osx:
hdiutil detach /Volumes/RAMDisk
testvsub-race:
@set -e; for pkg in $(GOPACKAGES); do \
echo; echo "___ testing subpkg $$pkg"; \
CGO_ENABLED=1 $(GO) test -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -race -timeout $(RACE_TEST_TIMEOUT) $$pkg || break; \
echo; echo "999 done testing subpkg $$pkg"; \
done
bench:
$(GO) test $(GOPACKAGES) -bench=. -run=NoneZ -timeout=127m $(TESTFLAGS)
# Run test suite with coverage enabled
cover:
mkdir -p build
$(MAKE) test TESTFLAGS="-coverprofile=build/coverage.out"
# Run test suite with coverage enabled and view coverage results in browser
cover-viz: cover
go tool cover -html=build/coverage/all.out
$(GO) tool cover -html=build/coverage.out
pilosa: vendor
go build -ldflags $(LDFLAGS) $(FLAGS) $(CLONE_URL)/cmd/pilosa
# Build featurebase
build:
$(GO) build -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/featurebase
release-build: vendor
ifdef DOCKER_BUILD
make docker-build FLAGS="-o build/pilosa-$(IDENTIFIER)/pilosa"
else
make pilosa FLAGS="-o build/pilosa-$(IDENTIFIER)/pilosa"
package:
GOOS=$(GOOS) GOARCH=$(GOARCH) $(MAKE) build
GOOS=$(GOOS) GOARCH=$(GOARCH) $(MAKE) build-fbsql
GOARCH=$(GOARCH) VERSION=$(VERSION) nfpm package --packager deb --target featurebase.$(VERSION).$(GOARCH).deb
GOARCH=$(GOARCH) VERSION=$(VERSION) nfpm package --packager rpm --target featurebase.$(VERSION).$(GOARCH).rpm
# We allow setting a custom docker-compose "project". Multiple of the
# same docker-compose environment can exist simultaneously as long as
# they use different projects (the project name is prepended to
# container names and such). This is useful in a CI environment where
# we might be running multiple instances of the tests concurrently.
PROJECT ?= clustertests
DOCKER_COMPOSE = docker-compose -p $(PROJECT)
# Run cluster integration tests using docker. Requires docker daemon to be
# running and docker-compose to be installed.
clustertests: vendor
$(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml down
$(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml build
$(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml up -d pilosa1 pilosa2 pilosa3
PROJECT=$(PROJECT) $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml run client1
$(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml down
# Run the cluster tests with authentication enabled
AUTH_ARGS="-c /go/src/github.com/featurebasedb/featurebase/internal/clustertests/testdata/featurebase.conf"
authclustertests: vendor
CLUSTERTESTS_FB_ARGS=$(AUTH_ARGS) $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml down
CLUSTERTESTS_FB_ARGS=$(AUTH_ARGS) $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml build
CLUSTERTESTS_FB_ARGS=$(AUTH_ARGS) $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml up -d pilosa1 pilosa2 pilosa3
PROJECT=$(PROJECT) ENABLE_AUTH=1 $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml run client1
CLUSTERTESTS_FB_ARGS=$(AUTH_ARGS) $(DOCKER_COMPOSE) -f internal/clustertests/docker-compose.yml down
# Install FeatureBase and IDK
install: install-featurebase install-idk install-fbsql
install-featurebase:
$(GO) install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/featurebase
install-idk:
$(MAKE) -C ./idk install
install-fbsql:
CGO_ENABLED=1 $(GO) install ./cmd/fbsql
# Build the lattice assets
build-lattice:
docker build -t lattice:build ./lattice
export LATTICE=`docker create lattice:build`; docker cp $$LATTICE:/lattice/. ./lattice/build && docker rm $$LATTICE
# `go generate` protocol buffers
generate-protoc: require-protoc require-protoc-gen-gofast
$(GO) generate github.com/featurebasedb/featurebase/v3/pb
# `go generate` statik assets (lattice UI)
generate-statik: build-lattice require-statik
$(GO) generate github.com/featurebasedb/featurebase/v3/statik
# `go generate` statik assets (lattice UI) in Docker
generate-statik-docker: build-lattice
docker run --rm -t -v $(PWD):/pilosa golang:1.15.8 sh -c "go get github.com/rakyll/statik && /go/bin/statik -src=/pilosa/lattice/build -dest=/pilosa -f"
# `go generate` stringers
generate-stringer:
$(GO) generate github.com/featurebasedb/featurebase/v3
generate-pql: require-peg
cd pql && peg -inline pql.peg && cd ..
generate-proto-grpc: require-protoc require-protoc-gen-go
protoc -I proto proto/pilosa.proto --go_out=plugins=grpc:proto
# address re-generation here only if we need to
# protoc -I proto proto/vdsm.proto --go_out=plugins=grpc:proto
# `go generate` all needed packages
generate: generate-protoc generate-statik generate-stringer generate-pql
# Create release using Docker
docker-release:
$(MAKE) docker-build GOOS=linux GOARCH=amd64
$(MAKE) docker-build GOOS=linux GOARCH=arm64
$(MAKE) docker-build GOOS=darwin GOARCH=amd64
$(MAKE) docker-build GOOS=darwin GOARCH=arm64
# Build a release in Docker
docker-build: vendor
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--build-arg MAKE_FLAGS="TRIAL_DEADLINE=$(TRIAL_DEADLINE) GOOS=$(GOOS) GOARCH=$(GOARCH)" \
--build-arg SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \
--target pilosa-builder \
--tag featurebase:build .
docker create --name featurebase-build featurebase:build
mkdir -p build/featurebase-$(VERSION_ID)
docker cp featurebase-build:/pilosa/build/. ./build/featurebase-$(VERSION_ID)
cp NOTICE install/featurebase.conf install/featurebase*.service ./build/featurebase-$(VERSION_ID)
docker rm featurebase-build
tar -cvz -C build -f build/featurebase-$(VERSION_ID).tar.gz featurebase-$(VERSION_ID)/
# Create Docker image from Dockerfile
docker-image: vendor
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--build-arg MAKE_FLAGS="TRIAL_DEADLINE=$(TRIAL_DEADLINE)" \
--tag featurebase:$(VERSION) .
@echo Created docker image: featurebase:$(VERSION)
docker-image-featurebase: vendor
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--file Dockerfile-dax \
--tag dax/featurebase .
docker-image-featurebase-linux-amd64: vendor
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--platform linux/amd64 \
--file Dockerfile-dax \
--tag dax/featurebase .
docker-image-featurebase-test: vendor
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--file Dockerfile-clustertests \
--tag dax/featurebase-test .
# build-for-quick builds a linux featurebase binary outside of docker
# (which is much faster for some reason), and places it in the .quick
# subdirectory.
build-for-quick:
GOOS=linux $(MAKE) build FLAGS="-o .quick/fb_linux"
# docker-image-featurebase-quick uses a pre-built featurebase binary
# to quickly create a fresh docker image without needing to send the
# context of the featurebase top level directory.
docker-image-featurebase-quick: build-for-quick
docker build \
--build-arg GO_VERSION=$(GO_VERSION) \
--file Dockerfile-dax-quick \
--tag dax/featurebase ./.quick/
docker-image-datagen: vendor
docker build --tag dax/datagen --file Dockerfile-datagen .
get-account-id:
$(eval AWS_ACCOUNTID := $(shell aws sts get-caller-identity --output=json | jq -r .Account))
ecr-push-featurebase: docker-login
echo "Pushing to account $(AWS_ACCOUNTID), profile $(AWS_PROFILE)"
docker tag dax/featurebase:latest $(AWS_ACCOUNTID).dkr.ecr.us-east-2.amazonaws.com/dax/featurebase:latest
docker push $(AWS_ACCOUNTID).dkr.ecr.us-east-2.amazonaws.com/dax/featurebase:latest
ecr-push-datagen: docker-login
docker tag dax/datagen:latest $(AWS_ACCOUNTID).dkr.ecr.us-east-2.amazonaws.com/dax/datagen:latest
docker push $(AWS_ACCOUNTID).dkr.ecr.us-east-2.amazonaws.com/dax/datagen:latest
docker-login: get-account-id
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin $(AWS_ACCOUNTID).dkr.ecr.us-east-2.amazonaws.com
# Create docker image (alias)
docker: docker-image # alias
# Tag and push a Docker image
docker-tag-push: vendor
docker tag "featurebase:$(VERSION)" $(DOCKER_TARGET)
docker push $(DOCKER_TARGET)
@echo Pushed docker image: $(DOCKER_TARGET)
# These commands (docker-idk and docker-idk-tag-push)
# are designed to be used in CI.
# docker-idk builds idk docker images and tags them - intended for use in CI.
docker-idk: vendor
docker build \
-f idk/Dockerfile \
--build-arg GO_VERSION=$(GO_VERSION) \
--build-arg MAKE_FLAGS="GOOS=$(GOOS) GOARCH=$(GOARCH) BUILD_CGO=$(BUILD_CGO)" \
--tag registry.gitlab.com/molecula/featurebase/idk:$(VERSION_ID) .
@echo Created docker image: registry.gitlab.com/molecula/featurebase/idk:$(VERSION_ID)
# docker-idk-tag-push pushes tagged docker images to the GitLab container
# registry - intended for use in CI.
docker-idk-tag-push:
docker push registry.gitlab.com/molecula/featurebase/idk:$(VERSION_ID)
@echo Pushed docker image: registry.gitlab.com/molecula/featurebase/idk:$(VERSION_ID)
# Run golangci-lint
golangci-lint: require-golangci-lint
golangci-lint run --timeout 3m --skip-files '.*\.peg\.go'
# Alias
linter: golangci-lint
# Better alias
ocd: golangci-lint
######################
# Build dependencies #
######################
# Verifies that needed build dependency is installed. Errors out if not installed.
require-%:
$(if $(shell command -v $* 2>/dev/null),\
$(info Verified build dependency "$*" is installed.),\
$(error Build dependency "$*" not installed. To install, try `make install-$*`))
install-build-deps: install-protoc-gen-gofast install-protoc install-statik install-peg
install-statik:
go install github.com/rakyll/statik@latest
install-protoc-gen-gofast:
GO111MODULE=off $(GO) get -u github.com/gogo/protobuf/protoc-gen-gofast
install-protoc:
@echo This tool cannot automatically install protoc. Please download and install protoc from https://google.github.io/proto-lens/installing-protoc.html
@echo On mac, brew install protobuf seems to work.
@echo As of the commit that added this line, protoc-gen-gofast was at 226206f39bd7, and the protoc version in use was:
@echo $$ protoc --version
@echo libprotoc 3.19.4
install-peg:
GO111MODULE=off $(GO) get github.com/pointlander/peg
install-golangci-lint:
GO111MODULE=off $(GO) get github.com/golangci/golangci-lint/cmd/golangci-lint
test-external-lookup:
$(GO) test . -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -run ^TestExternalLookup$$ -externalLookupDSN $(EXTERNAL_LOOKUP_DSN)
bnf:
ebnf2railroad --no-overview-diagram --no-optimizations ./sql3/sql3.ebnf
#################################
# fbsql builds in docker
#################################
# This allows multiple concurrent builds to happen in CI without
# creating container name conflicts and such. (different BUILD_NAMEs
# are passed in from gitlab-ci.yml)
BUILD_NAME ?= fbsql-build
LDFLAGS_STATIC="-linkmode external -extldflags \"-static\" -X 'github.com/featurebasedb/featurebase/v3/fbsql.Version=$(VERSION)' -X 'github.com/featurebasedb/featurebase/v3/fbsql.BuildTime=$(BUILD_TIME)' "
UNAME_P := $(shell uname -p)
BUILD_CGO ?= 0
# Build fbsql
build-fbsql:
@echo GOOS=$(GOOS) GOARCH=$(GOARCH) uname -p=$(UNAME_P) build_cgo=$(BUILD_CGO)
ifeq ($(BUILD_CGO), 0)
make build-fbsql-non-cgo
endif
cp LICENSE README.md build/pilosa-$(IDENTIFIER)
tar -cvz -C build -f build/pilosa-$(IDENTIFIER).tar.gz pilosa-$(IDENTIFIER)/
@echo "Created release build: build/pilosa-$(IDENTIFIER).tar.gz"
release:
make release-build GOOS=darwin GOARCH=amd64
make release-build GOOS=linux GOARCH=amd64 DOCKER_BUILD=1
make release-build GOOS=linux GOARCH=386 DOCKER_BUILD=1
prerelease-build: vendor
make pilosa FLAGS="-o build/pilosa-master-$(GOOS)-$(GOARCH)/pilosa"
cp LICENSE README.md build/pilosa-master-$(GOOS)-$(GOARCH)
tar -cvz -C build -f build/pilosa-master-$(GOOS)-$(GOARCH).tar.gz pilosa-master-$(GOOS)-$(GOARCH)/
@echo "Created pre-release build: build/pilosa-master-$(GOOS)-$(GOARCH).tar.gz"
prerelease:
make prerelease-build GOOS=linux GOARCH=amd64
prerelease-upload: prerelease
aws s3 cp build/pilosa-master-linux-amd64.tar.gz s3://build.pilosa.com/pilosa-master-linux-amd64.tar.gz --acl public-read
install: vendor
go install -ldflags $(LDFLAGS) $(FLAGS) $(CLONE_URL)/cmd/pilosa
.protoc-gen-gofast: vendor
ifndef PROTOC
$(error "protoc is not available. please install protoc from https://github.com/google/protobuf/releases")
endif
go build -o .protoc-gen-gofast ./vendor/github.com/gogo/protobuf/protoc-gen-gofast
cp ./.protoc-gen-gofast $(GOPATH)/bin/protoc-gen-gofast
generate-protoc: .protoc-gen-gofast
go generate github.com/pilosa/pilosa/internal
generate-statik: statik
go generate github.com/pilosa/pilosa
generate: generate-protoc generate-statik
statik:
ifndef STATIK
go get github.com/rakyll/statik
ifeq ($(BUILD_CGO), 1)
make build-fbsql-cgo
endif
docker:
docker build -t "pilosa:$(VERSION)" --build-arg ldflags=$(LDFLAGS) .
@echo "Created image: pilosa:$(VERSION)"
build-fbsql-non-cgo:
CGO_ENABLED=0 $(GO) build -ldflags $(LDFLAGS) $(GO_BUILD_FLAGS) -o fbsql ./cmd/fbsql
docker-build:
docker run --rm -v $(PWD):/go/src/$(CLONE_URL) -w /go/src/$(CLONE_URL) -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) $(DOCKER_GOLANG_IMAGE) go build -ldflags $(LDFLAGS) $(FLAGS) $(CLONE_URL)/cmd/pilosa
build-fbsql-cgo:
ifeq ($(GOARCH), arm64)
CGO_ENABLED=1 $(GO) build -tags dynamic $(GO_BUILD_FLAGS) -o fbsql ./cmd/fbsql
endif
ifeq ($(GOARCH), amd64)
CC=/usr/bin/musl-gcc CGO_ENABLED=1 $(GO) build -tags "musl static" -ldflags $(LDFLAGS_STATIC) $(GO_BUILD_FLAGS) -o fbsql ./cmd/fbsql
endif
docker-build-fbsql: vendor
DOCKER_BUILDKIT=0 docker build \
--file Dockerfile-fbsql \
--build-arg GO_VERSION=$(GO_VERSION) \
--build-arg MAKE_FLAGS="GOOS=$(GOOS) GOARCH=$(GOARCH) BUILD_CGO=$(BUILD_CGO)" \
--build-arg GO_BUILD_FLAGS=$(GO_BUILD_FLAGS) \
--build-arg SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \
--target builder \
--tag fbsql:$(BUILD_NAME) .
mkdir -p build
docker create --name $(BUILD_NAME) fbsql:$(BUILD_NAME)
docker cp $(BUILD_NAME):/featurebase/fbsql ./build/fbsql_$(GOOS)_$(GOARCH)
docker rm $(BUILD_NAME)
docker-test:
docker run --rm -v $(PWD):/go/src/$(CLONE_URL) -w /go/src/$(CLONE_URL) $(DOCKER_GOLANG_IMAGE) go test $(TESTFLAGS) $(PKGS)

26
NOTES
View file

@ -1,26 +0,0 @@
Index Column
┌───────────▼────────────────────────────┐
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
Row──▶0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│────────────────────────────────────────┤
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│────────────────────────────────────────┤
F ▶│0000000000000000000000000000000000000000│
r ││0000000000000000000000000000000000000000│
a ││0000000000000000000000000000000000000000│
m ││0000000000000000000000000000000000000000│
e ▶│0000000000000000000000000000000000000000│
└────────────────────────────────────────┘
▲───────────▲
Slice
Fragment=intersection of frame & slice

109
NOTICE Normal file
View file

@ -0,0 +1,109 @@
Software license
================
Copyright (C) 2017-2021 Molecula Corp. All rights reserved.
Third-party software licenses
=============================
The file /lru/lru.go contains a redistribution of lru
(github.com/golang/groupcache/lru); the license follows:
Copyright 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The file /roaring/btree.go contains a modified redistribution of b
(https://github.com/cznic/b); the license follows:
Copyright (c) 2014 The b Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the names of the authors nor the names of the
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The file /server/tlsconfig.go contains a modified redistribution of bridge
(https://github.com/robustirc/bridge); the license follows:
Copyright © 2014-2015 The RobustIRC Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of RobustIRC nor the names of contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The files /logger/filewriter.go and /logger/filewriter_test.go contain a modified redistribution of reopen (github.com/client9/reopen); the license follows:
The MIT License (MIT)
Copyright (c) 2015 Nick Galbreath
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

45
OPENSOURCE.md Normal file
View file

@ -0,0 +1,45 @@
## User Contribution Guidelines for FeatureBase
Thank you for your interest in contributing to FeatureBase! We appreciate your support in making this open-source project even better. Here are some guidelines to help you get started with contributing to FeatureBase:
1. Familiarize Yourself with the Project:
- Visit the FeatureBase website at www.featurebase.com to understand the project's goals, capabilities, and features.
- Read the documentation available on the website, including the installation guide, configuration options, and data modeling concepts.
- Explore the codebase by cloning the repository and reviewing the source code.
2. Join the Community:
- Visit the FeatureBase community page at https://www.featurebase.com/community to learn more about the project's community and how to get involved.
- Join the Discord server at https://discord.gg/FBn2vEp7Na to chat with other contributors and users, ask questions, and share your ideas.
3. Set Up Your Development Environment:
- Ensure you have Go installed on your machine. Make sure your shell's search path includes the go/bin directory.
- Clone the FeatureBase repository or download it as a zip file from the repository's page.
- Follow the "Build FeatureBase Server from source" instructions in the README file to compile the server binary and the ingester binaries.
4. Choose a Contribution Area:
- Identify the area you'd like to contribute to, such as bug fixes, new features, performance improvements, documentation updates, or community support.
- Check the issue tracker on the repository or the FeatureBase community for open issues or feature requests that align with your interests and skills. Alternatively, propose your own idea by creating a new issue.
5. Create a New Branch:
- Before making any changes, create a new branch in the repository's Git repository. This branch will contain your contributions.
- Give your branch a descriptive name that reflects the nature of your contribution.
6. Make Your Changes:
- Follow the coding style and conventions used in the existing codebase.
- Write clear and concise commit messages for each logical change.
- If you're introducing new features or modifying existing behavior, make sure to update the documentation to reflect the changes.
7. Test Your Changes:
- Run the existing test suite to ensure that your modifications do not introduce any regressions.
- If applicable, write additional tests to cover the changes you made.
- Document any new testing procedures required for your contribution.
8. Submitting Your Contribution:
- Push your branch to the main repository or create a fork and submit a pull request to the main repository.
- Provide a detailed description of your changes, including the problem you solved and the approach you took.
- Be responsive to any feedback or suggestions provided by the project maintainers or other contributors.
- Once your contribution is approved, it will be reviewed and merged into the main codebase.
Please note that by contributing to FeatureBase, you agree that your contributions will be licensed under the Apache 2.0 license, which governs the project.
Thank you for considering contributing to FeatureBase! Your contributions are valuable and help improve the project for everyone.

View file

@ -1,69 +0,0 @@
Development Environment
=======================
Install Go versions 1.6.2+ or 1.7 for your platform.
Fork `github.com/pilosa/pilosa` to your own account. The forked repo will be private.
Make sure `$GOPATH` environment variable points to your Go working directory and `$PATH` incudes `$GOPATH/bin`.
Create a directory (note that we use `github.com/pilosa`, NOT `github.com/USER`) and clone your own Pilosa repo:
```sh
mkdir -p ${GOPATH}/src/github.com/pilosa && cd $_
git clone git@github.com:${USER}/pilosa.git
```
`cd` to your pilosa directory:
```sh
cd ${GOPATH}/src/github.com/pilosa/pilosa
```
Install `dep` to manage dependencies:
```sh
go get -u github.com/golang/dep/cmd/dep
```
Install Pilosa command line tools:
```sh
make install
# or:
# dep ensure && go install github.com/pilosa/pilosa/cmd/...
```
Running `pilosa` should now run a Pilosa instance.
In order to sync your fork with upstream Pilosa repo, add an *upstream* to your repo:
```sh
cd ${GOPATH}/src/github.com/pilosa/pilosa
git remote add upstream git@github.com:pilosa/pilosa.git
```
Before starting to work on a task, sync your branch with the upstream:
```sh
git fetch upstream
git checkout master
git merge upstream/master
```
Create a branch for the task:
```sh
git checkout -b a-branch-for-the-task
```
Update the code in the branch, and commit it.
Push it to your own repo:
```sh
git push --set-upstream origin a-branch-for-the-task
```
All left to do is creating a pull request on github.com.

View file

@ -1,71 +1,72 @@
<p>
<a href="https://www.pilosa.com">
<img src="https://www.pilosa.com/img/logo.svg" width="50%">
</a>
</p>
# FeatureBase Community
[![Build Status](https://travis-ci.org/pilosa/pilosa.svg?branch=master)](https://travis-ci.org/pilosa/pilosa)
[![GoDoc](https://godoc.org/github.com/pilosa/pilosa?status.svg)](https://godoc.org/github.com/pilosa/pilosa)
[![Go Report Card](https://goreportcard.com/badge/github.com/pilosa/pilosa)](https://goreportcard.com/report/github.com/pilosa/pilosa)
[![license](https://img.shields.io/github/license/pilosa/pilosa.svg)](https://github.com/pilosa/pilosa/blob/master/LICENSE)
[![CLA Assistant](https://cla-assistant.io/readme/badge/pilosa/pilosa)](https://cla-assistant.io/pilosa/pilosa)
[![GitHub release](https://img.shields.io/github/release/pilosa/pilosa.svg)](https://github.com/pilosa/pilosa/releases)
FeatureBase Community is now archived and no longer maintained.
## An open source, distributed bitmap index.
- [Docs](#docs)
- [Getting Started](#getting-started)
- [Data Model](#data-model)
- [Query Language](#query-language)
- [Client Libraries](#client-libraries)
- [Get Support](#get-support)
- [Contributing](#contributing)
* [FeatureBase Community Help](https://github.com/FeatureBaseDB/FB-community-help)
## Docs
See our [Documentation](https://www.pilosa.com/docs/) for information about installing and working with Pilosa.
## Pilosa is now FeatureBase
As of September 7, 2022, the Pilosa project is now FeatureBase. The core of the project remains the same: FeatureBase is the first real-time distributed database built entirely on bitmaps. (More information about updated capabilities and improvements below.)
FeatureBase delivers low-latency query results, regardless of throughput or query volumes, on fresh data with extreme efficiency. It works because bitmaps are faster, simpler, and far more I/O efficient than traditional column-oriented data formats. With FeatureBase, you can ingest data from batch data sources (e.g. S3, CSV, Snowflake, BigQuery, etc.) and/or streaming data sources (e.g. Kafka/Confluent, Kinesis, Pulsar).
For more information about FeatureBase, please visit [www.featurebase.com][HomePage].
## Getting Started
1. [Install Pilosa](https://www.pilosa.com/docs/installation/).
* [Learn how to install FeatureBase Community](https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/community/com-getstart/com-getstart-home.md)
2. [Start Pilosa](https://www.pilosa.com/docs/getting-started/#starting-pilosa) with the default configuration:
### Build FeatureBase Server from source
```shell
pilosa server
```
and verify that it's running:
```shell
curl localhost:10101/nodes
```
0. Install go. Ensure that your shell's search path includes the go/bin directory.
1. Clone the FeatureBase repository (or download as zip).
2. In the featurebase directory, run `make install` to compile the FeatureBase server binary. By default, it will be installed in the go/bin directory.
3. In the idk directory, run `make install` to compile the ingester binaries. By default, they will be installed in the go/bin directory.
4. Run `featurebase server --handler.allowed-origins=http://localhost:3000` to run FeatureBase server with default settings (learn more about configuring FeatureBase at the link below). The `--handler.allowed-origins` parameter allows the standalone web UI to talk to the server; this can be omitted if the web UI is not needed.
5. Run `curl localhost:10101/status` to verify the server is running and accessible.
3. Follow along with the [Sample Project](https://www.pilosa.com/docs/getting-started/#sample-project) to get a better understanding of Pilosa's capabilities.
### Data Model
Because FeatureBase is built on bitmaps, there is bit of a learning curve to grasp how your data is represented.
* [Learn about Data Modeling](https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/concepts/concepts-home.md)
## Data Model
### Ingest Data and Query
Check out how the Pilosa [Data Model](https://www.pilosa.com/docs/data-model/) works.
* [Learn how to ingest data from multiple data sources](https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/community/com-ingest/com-ingest-manage.md)
## Community
## Query Language
You can email us at community@featurebase.com and [learn more about contributing](https://github.com/FeatureBaseDB/featurebase/blob/master/OPENSOURCE.md).
You can interact with Pilosa directly in the console using the [Pilosa Query Language](https://www.pilosa.com/docs/query-language/) (PQL).
Chat with us: [https://discord.gg/FBn2vEp7Na][Discord]
## What's Changed Since the Pilosa Days?
## Client Libraries
A lot has changed since the days of Pilosa. This list highlights some new capabilites included in FeatureBase. We have also made signficant improvements to the performance, scalability, and stability of the FeatureBase product.
There are supported libraries for the following languages:
- [Go](https://www.pilosa.com/docs/client-libraries/#go)
- [Java](https://www.pilosa.com/docs/client-libraries/#java)
- [Python](https://www.pilosa.com/docs/client-libraries/#python)
* Query Languages: FeatureBase supports Pilosa Query Language (PQL), as well as SQL
* Stream and Batch Ingest: Combine real-time data streams with batch historical data and act on it within milliseconds.
* Mutable: Perform inserts, updates, and deletes at scale, in real time and on-the-fly. This is key for meeting data compliance requirements, and for reflecting the constantly-changing nature of high-volume data.
* Multi-Valued Set Fields: Store multiple comma-delimited values within a single field while *increasing* query performance of counts, TopKs, etc.
* Time Quantums: Setting a time quantum on a field creates extra views which allow ranged Row queries down to the time interval specified. For example, if the time quantum is set to YMD, ranged Row queries down to the granularity of a day are supported.
* RBF storage backend: this is a new compressed bitmap format which improves performance in a number of ways: ACID support on a per shard basis, prevents issues with the number of open files, reduces memory allocation and lock contention for reads, provides more consistent garbage collection, and allows backups to run concurrently with writes. However, because of this change, Pilosa backup files cannot be restored into FeatureBase.
## Get Support
## License
There are [several channels](https://www.pilosa.com/community/#support) available for you to reach out to us for support.
FeatureBase is licensed under the [Apache License, Version 2.0][License]
## Contributing
Pilosa is an open source project. Please see our [Contributing Guide](CONTRIBUTING.md) for information about how to get involved.
[Community]: https://github.com/FeatureBaseDB/FB-community-help/tree/main
[Install]:https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/community/com-getstart/com-getstart-home.md
[Config]: https://github.com/FeatureBaseDB/FB-community-help/tree/main/docs/community/com-config
[DataModel]: https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/concepts/concepts-home.md
[Discord]: https://discord.gg/FBn2vEp7Na
[HomePage]: http://featurebase.com?utm_campaign=Open%20Source&utm_source=GitHub
[Ingest]: https://github.com/FeatureBaseDB/FB-community-help/blob/main/docs/community/com-ingest/com-ingest-manage.md
[License]: http://www.apache.org/licenses/LICENSE-2.0
[PQL]: https://docs.featurebase.com/docs/pql-guide/pql-home/?utm_campaign=Open%20Source&utm_source=GitHub
[SQL]: https://docs.featurebase.com/docs/sql-guide/sql-guide-home/?utm_campaign=Open%20Source&utm_source=GitHub

3525
api.go Normal file

File diff suppressed because it is too large Load diff

204
api/client/grpc.go Normal file
View file

@ -0,0 +1,204 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package client
import (
"context"
"crypto/tls"
"sync"
"github.com/featurebasedb/featurebase/v3/logger"
pb "github.com/featurebasedb/featurebase/v3/proto"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)
const maxMsgSize = 1024 * 1024 * 100 // 100 megs ought to be enough for anybody!
// GRPCClient is a client for working with the gRPC server.
type GRPCClient struct {
dialTargets []string
tlsConfig *tls.Config
logger logger.Logger
mu sync.RWMutex
conn *grpc.ClientConn
targetIndex int
}
// NewGRPCClient returns a new instance of GRPCClient.
func NewGRPCClient(dialTargets []string, tlsConfig *tls.Config, logger logger.Logger) (*GRPCClient, error) {
c := &GRPCClient{
dialTargets: dialTargets,
tlsConfig: tlsConfig,
logger: logger,
}
// resetConn sets GRPCClient.conn when it doesn't
// exist yet.
if err := c.resetConn(); err != nil {
return nil, errors.Wrap(err, "setting connection")
}
return c, nil
}
// resetConn resets the gRPC client connection. This method
// can also be used to initially set the client connection
// because it only tries to first close the connection if
// the connection already exists.
func (c *GRPCClient) resetConn() error {
c.mu.Lock()
defer c.mu.Unlock()
// If an existing connection exists, close it first.
if c.conn != nil {
if err := c.conn.Close(); err != nil {
return errors.Wrap(err, "closing existing connection")
}
}
var opts []grpc.DialOption
if c.tlsConfig != nil {
creds := credentials.NewTLS(c.tlsConfig)
opts = append(opts, grpc.WithTransportCredentials(creds))
} else {
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)))
var err error
if c.conn, err = grpc.Dial(c.dialTargets[c.getTargetIndex()], opts...); err != nil {
return errors.Wrap(err, "creating new grpc client")
}
return nil
}
// getTargetIndex gets the current target index, then increments it for
// next time. Unprotected.
func (c *GRPCClient) getTargetIndex() int {
if len(c.dialTargets) == 0 {
return 0
}
ret := c.targetIndex
c.targetIndex = (c.targetIndex + 1) % len(c.dialTargets) // cycle through dialTargets
return ret
}
// Close closes any connections the client has opened.
func (c *GRPCClient) Close() error {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn != nil {
return c.conn.Close()
}
return nil
}
// Conn returns the gRPC client connection. If the connection
// has gone into state `TransientFailure`, this method tries
// to reset the connection and return that new connection.
func (c *GRPCClient) Conn() *grpc.ClientConn {
c.mu.RLock()
if c.conn == nil {
c.mu.RUnlock()
return nil
} else if c.conn.GetState() != connectivity.TransientFailure {
defer c.mu.RUnlock()
return c.conn
}
c.mu.RUnlock()
if err := c.resetConn(); err != nil {
c.logger.Errorf("error resetting connection: %s", err)
}
c.mu.RLock()
defer c.mu.RUnlock()
return c.conn
}
// Query returns a stream of RowResponse for the given index and PQL string.
func (c *GRPCClient) Query(ctx context.Context, index string, pql string) (pb.StreamClient, error) {
conn := c.Conn()
if conn == nil {
return nil, errors.New("client has not established a grpc connection")
}
grpcClient := pb.NewPilosaClient(conn)
stream, err := grpcClient.QueryPQL(ctx, &pb.QueryPQLRequest{
Index: index,
Pql: pql,
})
if err != nil {
return nil, errors.Wrap(err, "getting stream")
} else if stream == nil {
return nil, errors.New("could not create stream")
}
return stream, err
}
// QueryUnary returns a TableResponse for the given index and PQL string.
func (c *GRPCClient) QueryUnary(ctx context.Context, index string, pql string) (*pb.TableResponse, error) {
conn := c.Conn()
if conn == nil {
return nil, errors.New("client has not established a grpc connection")
}
grpcClient := pb.NewPilosaClient(conn)
return grpcClient.QueryPQLUnary(ctx, &pb.QueryPQLRequest{
Index: index,
Pql: pql,
})
}
// Inspect returns a stream of RowResponse for the given index, columns, and filters.
// It is intended to mimic something like "select [fields] from table where recordID IN (...)".
func (c *GRPCClient) Inspect(ctx context.Context, index string, columnIDs []uint64, columnKeys []string, query string, fieldFilters []string, limit, offset uint64) (pb.StreamClient, error) {
conn := c.Conn()
if conn == nil {
return nil, errors.New("client has not established a grpc connection")
}
if len(columnIDs) > 0 && len(columnKeys) > 0 {
return nil, errors.New("only provide column ids or keys, not both")
}
// Convert columns to proto type IdsOrKeys.
idsOrKeys := &pb.IdsOrKeys{}
if len(columnKeys) > 0 {
idsOrKeys.Type = &pb.IdsOrKeys_Keys{Keys: &pb.StringArray{Vals: columnKeys}}
} else {
idsOrKeys.Type = &pb.IdsOrKeys_Ids{Ids: &pb.Uint64Array{Vals: columnIDs}}
}
grpcClient := pb.NewPilosaClient(conn)
stream, err := grpcClient.Inspect(ctx, &pb.InspectRequest{
Index: index,
Columns: idsOrKeys,
FilterFields: fieldFilters,
Limit: limit,
Offset: offset,
Query: query,
})
if err != nil {
return nil, errors.Wrap(err, "getting stream")
} else if stream == nil {
return nil, errors.New("could not create stream")
}
return stream, err
}

987
api_directive.go Normal file
View file

@ -0,0 +1,987 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"context"
"io"
"log"
"sync"
"github.com/featurebasedb/featurebase/v3/dax"
"github.com/featurebasedb/featurebase/v3/dax/computer"
"github.com/featurebasedb/featurebase/v3/dax/storage"
"github.com/featurebasedb/featurebase/v3/disco"
"github.com/pkg/errors"
)
// ApplyDirective applies a Directive received, from the Controller, at the
// /directive endpoint.
func (api *API) ApplyDirective(ctx context.Context, d *dax.Directive) error {
// Get the current directive for comparison.
previousDirective := api.holder.Directive()
// Check that incoming version is newer.
// Note: 0 is an invalid Directive version. This decision was made because
// previousDirective is not a pointer to a directive, but a concrete
// Directive. Which means we can't check for nil, and by default it has a
// version of 0. So in order to ensure the version has increased, we need to
// require that incoming directive versions are greater than 0.
if d.Version == 0 {
return errors.Errorf("directive version cannot be 0")
} else if previousDirective.Version >= d.Version {
return errors.Errorf("directive version mismatch, got %d, but already have %d", d.Version, previousDirective.Version)
}
// Handle the operations based on the directive method.
switch d.Method {
case dax.DirectiveMethodDiff:
// In order to prevent adding too much code specific to handling a diff
// directive (e.g. adding something like an `enactDirectiveDiff()`
// method), we are instead going to build a full Directive based on the
// diff, and then proceed normally as if we had received a full
// Directive. We do that by copying the previous Directive and then
// applying the diffs to the copy.
newD := previousDirective.Copy()
// Apply the diffs from the incoming Directive to the new, copied
// Directive.
newD.ApplyDiff(d)
// Now proceed with the new diff as if we had received it as a full diff.
d = newD
case dax.DirectiveMethodFull:
// pass: normal operation
case dax.DirectiveMethodReset:
// Delete all tables.
if err := api.deleteAllIndexes(ctx); err != nil {
return errors.Wrap(err, "deleting all indexes")
}
// Set previousDirective to empty so the diff handles everything as new.
previousDirective = dax.Directive{}
case dax.DirectiveMethodSnapshot:
// TODO(tlt): this was the existing logic, but we should really diff the
// directive and ensure that overwriting the value in the cache doesn't
// have a negative effect.
api.holder.SetDirective(d)
return nil
default:
return errors.Errorf("invalid directive method: %s", d.Method)
}
// Cache this directive as the latest applied. There is functionality within
// the "enactDirective" stage of ApplyDirective which validates against this
// cached Directive, so it's important that it be set before calling
// enactDirective(). An example: when loading partition data from the
// Writelogger, there are validations to ensure that the partition being
// loaded is meant to be handled by this node; that validation is done
// against the cached Directive.
// TODO(tlt): despite what this comment says, this logic is not sound; we
// shouldn't be setting the directive until enactiveDirective() succeeds.
api.holder.SetDirective(d)
defer api.holder.SetDirectiveApplied(true)
return api.enactDirective(ctx, &previousDirective, d)
}
// deleteAllIndexes deletes all indexes handled by this node.
func (api *API) deleteAllIndexes(ctx context.Context) error {
indexes, err := api.Schema(ctx, false)
if err != nil {
return errors.Wrap(err, "getting schema")
}
for i := range indexes {
if err := api.DeleteIndex(ctx, indexes[i].Name); err != nil {
return errors.Wrapf(err, "deleting index: %s", indexes[i].Name)
}
}
return nil
}
// directiveJobType allows us to switch on jobType in the directiveWorker in
// order to use a single worker pool for all job types (as opposed to having a
// separate worker pool for each job type).
type directiveJobType interface {
// We have this method just to prevent *any* struct from implementing this
// interface automatically. But, interestingly enough, we don't actually
// have to have this method on the implementation because we embed the
// interface.
isJobType() bool
}
type directiveJobTableKeys struct {
directiveJobType
idx *Index
tkey dax.TableKey
partition dax.PartitionNum
}
type directiveJobFieldKeys struct {
directiveJobType
tkey dax.TableKey
field dax.FieldName
}
type directiveJobShards struct {
directiveJobType
tkey dax.TableKey
shard dax.ShardNum
}
// directiveWorker is a worker in a worker pool which handles portions of a
// directive. Multiple instances of directiveWorker run in goroutines in order
// to load data from snapshotter and writelogger concurrently. Note: unlike the
// api.ingestWorkerPool, of which one pool is always running, the
// directiveWorker pool is only running during the life of the
// api.ApplyDirective call. Technically, this means that multiple
// directiveWorker pools could be active at the same time, but we should never
// be running more than once instance of ApplyDirective concurrently.
func (api *API) directiveWorker(ctx context.Context, jobs <-chan directiveJobType, errs chan<- error) {
for j := range jobs {
switch job := j.(type) {
case directiveJobTableKeys:
if err := api.loadTableKeys(ctx, job.idx, job.tkey, job.partition); err != nil {
errs <- errors.Wrapf(err, "loading table keys: %s, %s", job.tkey, job.partition)
}
case directiveJobFieldKeys:
if err := api.loadFieldKeys(ctx, job.tkey, job.field); err != nil {
errs <- errors.Wrapf(err, "loading field keys: %s, %s", job.tkey, job.field)
}
case directiveJobShards:
if err := api.loadShard(ctx, job.tkey, job.shard); err != nil {
errs <- errors.Wrapf(err, "loading shard: %s, %s", job.tkey, job.shard)
}
default:
errs <- errors.Errorf("unsupported job type: %T %[1]v", job)
}
select {
case <-ctx.Done():
return
default:
// continue pulling jobs off the channel
}
}
}
func (api *API) enactDirective(ctx context.Context, fromD, toD *dax.Directive) error {
// enactTables is called before the jobs that run in the worker pool because
// it probably makes sense to apply the schema before trying to load data
// concurrently.
if err := api.enactTables(ctx, fromD, toD); err != nil {
return errors.Wrap(err, "enactTables")
}
// The following types use a shared pool of workers to run each
// directiveJobType.
var wg sync.WaitGroup
// open job channel
jobs := make(chan directiveJobType, api.directiveWorkerPoolSize)
errs := make(chan error)
done := make(chan struct{})
// Spin up n workers in goroutines that pull jobs from the jobs channel.
for i := 0; i < api.directiveWorkerPoolSize; i++ {
wg.Add(1)
go func() {
api.directiveWorker(ctx, jobs, errs)
defer wg.Done()
}()
}
// Wait for the WaitGroup counter to reach 0. When it has, indicate that
// we're done processing all jobs by closing the done channel.
go func() {
wg.Wait()
close(done)
}()
// Run through all the "enact" methods. These push jobs onto the jobs
// channel. Once all the jobs have been queued to the channel, we close the
// jobs channel. This allows the directiveWorkers to exit out of the
// function, which will then decrement the WaitGroup counter.
go func() {
api.pushJobsTableKeys(ctx, jobs, fromD, toD)
api.pushJobsFieldKeys(ctx, jobs, fromD, toD)
api.pushJobsShards(ctx, jobs, fromD, toD)
close(jobs)
}()
// Keep running until we get an error or until the done channel is closed.
// Note: the code is written such that only non-nil errors are pushed to the
// errs channel.
for {
select {
case err := <-errs:
return err
case <-done:
return nil
}
}
}
func (api *API) enactTables(ctx context.Context, fromD, toD *dax.Directive) error {
currentIndexes := api.holder.Indexes()
// Make a list of indexes that currently exist (from).
from := make(dax.TableKeys, 0, len(currentIndexes))
for _, idx := range currentIndexes {
qtid, err := dax.QualifiedTableIDFromKey(idx.Name())
if err != nil {
return errors.Wrap(err, "converting index name to qualified table id")
}
from = append(from, qtid.Key())
}
// TODO sanity check holder against fromD. We're getting existing
// indexes from holder, but in theory fromD should be
// identical. If we have an error in our directive-caching logic
// (it has happened before (just now, in fact!) and we'd be
// foolish to think it won't happen again), or we have schema
// mutations that are not going through the directive path, we
// could potentially catch them here.
// Make a list of tables that are in the directive (to) along with a map of
// tableKey to table (m).
m := make(map[dax.TableKey]*dax.QualifiedTable, len(toD.Tables))
to := make(dax.TableKeys, 0, len(toD.Tables))
for _, t := range toD.Tables {
m[t.Key()] = t
to = append(to, t.Key())
}
sc := newSliceComparer(from, to)
// Remove all indexes that are no longer part of the directive.
for _, tkey := range sc.removed() {
idx := string(tkey)
if err := api.DeleteIndex(ctx, idx); err != nil {
return errors.Wrapf(err, "deleting index: %s", tkey)
}
}
// Put partitions into a map by table.
partitionMap := toD.TranslatePartitionsMap()
// Add all indexes that weren't previously (but now are) a part of the
// directive.
for _, tkey := range sc.added() {
if qtbl, found := m[tkey]; !found {
return errors.Errorf("table '%s' was not in map", tkey)
} else if err := api.createTableAndFields(qtbl, partitionMap[tkey]); err != nil {
return err
}
}
// Check fields on all indexes present in both from and to.
for _, tkey := range sc.same() {
if err := api.enactFieldsForTable(ctx, tkey, fromD, toD); err != nil {
return errors.Wrapf(err, "enacting fields for table: '%s'", tkey)
}
}
return nil
}
func (api *API) enactFieldsForTable(ctx context.Context, tkey dax.TableKey, fromD, toD *dax.Directive) error {
qtid := tkey.QualifiedTableID()
fromT, err := fromD.Table(qtid)
if err != nil {
return errors.Wrap(err, "getting from table")
}
toT, err := toD.Table(qtid)
if err != nil {
return errors.Wrap(err, "getting to table")
}
// Get the index for tkey.
idx := api.holder.Index(string(tkey))
if idx == nil {
return errors.Errorf("index not found: %s", tkey)
}
sc := newSliceComparer(fromT.FieldNames(), toT.FieldNames())
// Add fields new to toT.
for _, fldName := range sc.added() {
if field, found := toT.Field(fldName); !found {
return dax.NewErrFieldDoesNotExist(fldName)
} else if err := createField(idx, field); err != nil {
return errors.Wrapf(err, "creating field: %s/%s", tkey, fldName)
}
}
// Remove fields which don't exist in toT.
for _, fldName := range sc.removed() {
if err := api.DeleteField(ctx, string(tkey), string(fldName)); err != nil {
return errors.Wrapf(err, "deleting field: %s/%s", tkey, fldName)
}
}
// // Update any field options which have changed for existing fields.
// for _, fldName := range sc.same() {
// // handle changed field options??
// }
return nil
}
func (api *API) pushJobsTableKeys(ctx context.Context, jobs chan<- directiveJobType, fromD, toD *dax.Directive) {
toPartitionsMap := toD.TranslatePartitionsMap()
// Get the diff between from/to directive.partitions.
partComp := newPartitionsComparer(fromD.TranslatePartitionsMap(), toPartitionsMap)
// Remove any partitions which are no longer assigned to this worker.
// TODO(tlt): currently, this is just removing the file lock on the
// resource; it's not actually removing the resource from the local
// computer. We should do that.
for tkey, partitions := range partComp.removed() {
qtid := tkey.QualifiedTableID()
for _, partition := range partitions {
api.serverlessStorage.RemoveTableKeyResource(qtid, partition)
}
}
// Loop over the partition map and load from Writelogger.
for tkey, partitions := range partComp.added() {
// Get index in order to find the translate stores (by partition) for
// the table.
idx := api.holder.Index(string(tkey))
if idx == nil {
log.Printf("index not found in holder: %s", tkey)
continue
}
// Update the cached version of translate partitions that we keep on the
// Index.
idx.SetTranslatePartitions(toPartitionsMap[tkey])
for _, partition := range partitions {
jobs <- directiveJobTableKeys{
idx: idx,
tkey: tkey,
partition: partition,
}
}
}
}
func (api *API) loadTableKeys(ctx context.Context, idx *Index, tkey dax.TableKey, partition dax.PartitionNum) error {
qtid := tkey.QualifiedTableID()
resource := api.serverlessStorage.GetTableKeyResource(qtid, partition)
if resource.IsLocked() {
api.logger().Warnf("skipping loadTableKeys (already held) %s %d", tkey, partition)
return nil
}
// load latest snapshot
if rc, err := resource.LoadLatestSnapshot(); err != nil {
return errors.Wrap(err, "loading table key snapshot")
} else if rc != nil {
defer rc.Close()
if err := api.TranslateIndexDB(ctx, string(tkey), int(partition), rc); err != nil {
return errors.Wrap(err, "restoring table keys")
}
}
// define write log loading in a function since we have to do it
// before and after locking
loadWriteLog := func() error {
writelog, err := resource.LoadWriteLog()
if err != nil {
return errors.Wrap(err, "getting write log reader for table keys")
}
if writelog == nil {
return nil
}
reader := storage.NewTableKeyReader(qtid, partition, writelog)
defer reader.Close()
store := idx.TranslateStore(int(partition))
for msg, err := reader.Read(); err != io.EOF; msg, err = reader.Read() {
if err != nil {
return errors.Wrap(err, "reading from log reader")
}
for key, id := range msg.StringToID {
if err := store.ForceSet(id, key); err != nil {
return errors.Wrapf(err, "forcing set id, key: %d, %s", id, key)
}
}
}
return nil
}
// 1st write log load
if err := loadWriteLog(); err != nil {
return err
}
// acquire lock on this partition's keys
if err := resource.Lock(); err != nil {
return errors.Wrap(err, "locking table key partition")
}
// reload writelog in case of changes between last load and
// lock. The resource object takes care of only loading new data.
return loadWriteLog()
}
func (api *API) pushJobsFieldKeys(ctx context.Context, jobs chan<- directiveJobType, fromD, toD *dax.Directive) {
// Get the diff between from/to directive.fields.
fieldComp := newFieldsComparer(fromD.TranslateFieldsMap(), toD.TranslateFieldsMap())
// Remove any field keys which are no longer assigned to this worker.
// TODO(tlt): currently, this is just removing the file lock on the
// resource; it's not actually removing the resource from the local
// computer. We should do that.
for tkey, fields := range fieldComp.removed() {
qtid := tkey.QualifiedTableID()
for _, field := range fields {
api.serverlessStorage.RemoveFieldKeyResource(qtid, field)
}
}
// Loop over the field map and load from Writelogger.
for tkey, fields := range fieldComp.added() {
for _, field := range fields {
jobs <- directiveJobFieldKeys{
tkey: tkey,
field: field,
}
}
}
}
func (api *API) loadFieldKeys(ctx context.Context, tkey dax.TableKey, field dax.FieldName) error {
qtid := tkey.QualifiedTableID()
resource := api.serverlessStorage.GetFieldKeyResource(qtid, field)
if resource.IsLocked() {
api.logger().Warnf("skipping loadFieldKeys (already held) %s %s", tkey, field)
return nil
}
// load latest snapshot
if rc, err := resource.LoadLatestSnapshot(); err != nil {
return errors.Wrap(err, "loading field key snapshot")
} else if rc != nil {
defer rc.Close()
if err := api.TranslateFieldDB(ctx, string(tkey), string(field), rc); err != nil {
return errors.Wrap(err, "restoring field keys")
}
}
// define write log loading in a function since we have to do it
// before and after locking
loadWriteLog := func() error {
writelog, err := resource.LoadWriteLog()
if err != nil {
return errors.Wrap(err, "getting write log reader for field keys")
}
if writelog == nil {
return nil
}
reader := storage.NewFieldKeyReader(qtid, field, writelog)
defer reader.Close()
// Get field in order to find the translate store.
fld := api.holder.Field(string(tkey), string(field))
if fld == nil {
log.Printf("field not found in holder: %s", field)
return nil
}
store := fld.TranslateStore()
for msg, err := reader.Read(); err != io.EOF; msg, err = reader.Read() {
if err != nil {
return errors.Wrap(err, "reading from log reader")
}
for key, id := range msg.StringToID {
if err := store.ForceSet(id, key); err != nil {
return errors.Wrapf(err, "forcing set id, key: %d, %s", id, key)
}
}
}
return nil
}
// 1st write log load
if err := loadWriteLog(); err != nil {
return err
}
// acquire lock on this partition's keys
if err := resource.Lock(); err != nil {
return errors.Wrap(err, "locking field key partition")
}
// reload writelog in case of changes between last load and
// lock. The resource object takes care of only loading new data.
return loadWriteLog()
}
func (api *API) pushJobsShards(ctx context.Context, jobs chan<- directiveJobType, fromD, toD *dax.Directive) {
// Put shards into a map by table.
shardMap := toD.ComputeShardsMap()
// Get the diff between from/to directive shards.
shardComp := newShardsComparer(fromD.ComputeShardsMap(), shardMap)
// Remove any shards which are no longer assigned to this worker.
// TODO(tlt): currently, this is just removing the file lock on the
// resource; it's not actually removing the resource from the local
// computer. We should do that.
for tkey, shards := range shardComp.removed() {
qtid := tkey.QualifiedTableID()
for _, shard := range shards {
partition := dax.PartitionNum(disco.ShardToShardPartition(string(tkey), uint64(shard), disco.DefaultPartitionN))
api.serverlessStorage.RemoveShardResource(qtid, partition, shard)
}
}
// Loop over the shard map and load from Writelogger.
for tkey, shards := range shardComp.added() {
for _, shard := range shards {
jobs <- directiveJobShards{
tkey: tkey,
shard: shard,
}
}
}
}
func (api *API) loadShard(ctx context.Context, tkey dax.TableKey, shard dax.ShardNum) error {
qtid := tkey.QualifiedTableID()
partition := dax.PartitionNum(disco.ShardToShardPartition(string(tkey), uint64(shard), disco.DefaultPartitionN))
resource := api.serverlessStorage.GetShardResource(qtid, partition, shard)
if resource.IsLocked() {
api.logger().Warnf("skipping loadShard (already held) %s %d", tkey, shard)
return nil
}
if rc, err := resource.LoadLatestSnapshot(); err != nil {
return errors.Wrap(err, "reading latest snapshot for shard")
} else if rc != nil {
defer rc.Close()
if err := api.RestoreShard(ctx, string(tkey), uint64(shard), rc); err != nil {
return errors.Wrap(err, "restoring shard data")
}
}
// define write log loading in a func because we do it twice.
loadWriteLog := func() error {
writelog, err := resource.LoadWriteLog()
if err != nil {
return errors.Wrap(err, "")
}
if writelog == nil {
return nil
}
reader := storage.NewShardReader(qtid, partition, shard, writelog)
defer reader.Close()
for logMsg, err := reader.Read(); err != io.EOF; logMsg, err = reader.Read() {
if err != nil {
return errors.Wrap(err, "reading from log reader")
}
switch msg := logMsg.(type) {
case *computer.ImportRoaringMessage:
req := &ImportRoaringRequest{
Clear: msg.Clear,
Action: msg.Action,
Block: msg.Block,
Views: msg.Views,
UpdateExistence: msg.UpdateExistence,
SuppressLog: true,
}
if err := api.ImportRoaring(ctx, msg.Table, msg.Field, msg.Shard, true, req); err != nil {
return errors.Wrapf(err, "import roaring, table: %s, field: %s, shard: %d", msg.Table, msg.Field, msg.Shard)
}
case *computer.ImportMessage:
req := &ImportRequest{
Index: msg.Table,
Field: msg.Field,
Shard: msg.Shard,
RowIDs: msg.RowIDs,
ColumnIDs: msg.ColumnIDs,
RowKeys: msg.RowKeys,
ColumnKeys: msg.ColumnKeys,
Timestamps: msg.Timestamps,
Clear: msg.Clear,
}
qcx := api.Txf().NewQcx()
defer qcx.Abort()
opts := []ImportOption{
OptImportOptionsClear(msg.Clear),
OptImportOptionsIgnoreKeyCheck(msg.IgnoreKeyCheck),
OptImportOptionsPresorted(msg.Presorted),
OptImportOptionsSuppressLog(true),
}
if err := api.Import(ctx, qcx, req, opts...); err != nil {
return errors.Wrapf(err, "import, table: %s, field: %s, shard: %d", msg.Table, msg.Field, msg.Shard)
}
case *computer.ImportValueMessage:
req := &ImportValueRequest{
Index: msg.Table,
Field: msg.Field,
Shard: msg.Shard,
ColumnIDs: msg.ColumnIDs,
ColumnKeys: msg.ColumnKeys,
Values: msg.Values,
FloatValues: msg.FloatValues,
TimestampValues: msg.TimestampValues,
StringValues: msg.StringValues,
Clear: msg.Clear,
}
qcx := api.Txf().NewQcx()
defer qcx.Abort()
opts := []ImportOption{
OptImportOptionsClear(msg.Clear),
OptImportOptionsIgnoreKeyCheck(msg.IgnoreKeyCheck),
OptImportOptionsPresorted(msg.Presorted),
OptImportOptionsSuppressLog(true),
}
if err := api.ImportValue(ctx, qcx, req, opts...); err != nil {
return errors.Wrapf(err, "import value, table: %s, field: %s, shard: %d", msg.Table, msg.Field, msg.Shard)
}
case *computer.ImportRoaringShardMessage:
req := &ImportRoaringShardRequest{
Remote: true,
Views: make([]RoaringUpdate, len(msg.Views)),
SuppressLog: true,
}
for i, view := range msg.Views {
req.Views[i] = RoaringUpdate{
Field: view.Field,
View: view.View,
Clear: view.Clear,
Set: view.Set,
ClearRecords: view.ClearRecords,
}
}
if err := api.ImportRoaringShard(ctx, msg.Table, msg.Shard, req); err != nil {
return errors.Wrapf(err, "import roaring shard table: %s, shard: %d", msg.Table, msg.Shard)
}
}
}
return nil
}
// 1st write log load
if err := loadWriteLog(); err != nil {
return err
}
// acquire lock on this partition's keys
if err := resource.Lock(); err != nil {
return errors.Wrap(err, "locking field key partition")
}
// reload writelog in case of changes between last load and
// lock. The resource object takes care of only loading new data.
return loadWriteLog()
}
//////////////////////////////////////////////////////////////
// sliceComparer is used to compare the differences between two slices of comparables.
type sliceComparer[K comparable] struct {
from []K
to []K
}
func newSliceComparer[K comparable](from []K, to []K) *sliceComparer[K] {
return &sliceComparer[K]{
from: from,
to: to,
}
}
// added returns the items which are present in `to` but not in `from`.
func (s *sliceComparer[K]) added() []K {
return thingsAdded(s.from, s.to)
}
// removed returns the items which are present in `from` but not in `to`.
func (s *sliceComparer[K]) removed() []K {
return thingsAdded(s.to, s.from)
}
// same returns the items which are in both `to` and `from`.
func (s *sliceComparer[K]) same() []K {
var same []K
for _, fromThing := range s.from {
for _, toThing := range s.to {
if fromThing == toThing {
same = append(same, fromThing)
break
}
}
}
return same
}
// thingsAdded returns the comparable things which are present in `to` but not
// in `from`.
func thingsAdded[K comparable](from []K, to []K) []K {
var added []K
for i := range to {
var found bool
for j := range from {
if from[j] == to[i] {
found = true
break
}
}
if !found {
added = append(added, to[i])
}
}
return added
}
// partitionsComparer is used to compare the differences between two maps of
// table:[]partition.
type partitionsComparer struct {
from map[dax.TableKey]dax.PartitionNums
to map[dax.TableKey]dax.PartitionNums
}
func newPartitionsComparer(from map[dax.TableKey]dax.PartitionNums, to map[dax.TableKey]dax.PartitionNums) *partitionsComparer {
return &partitionsComparer{
from: from,
to: to,
}
}
// added returns the partitions which are present in `to` but not in `from`. The
// results remain in the format of a map of table:[]partition.
func (p *partitionsComparer) added() map[dax.TableKey]dax.PartitionNums {
return partitionsAdded(p.from, p.to)
}
// removed returns the partitions which are present in `from` but not in `to`.
// The results remain in the format of a map of table:[]partition.
func (p *partitionsComparer) removed() map[dax.TableKey]dax.PartitionNums {
return partitionsAdded(p.to, p.from)
}
// partitionsAdded returns the partitions which are present in `to` but not in `from`.
func partitionsAdded(from map[dax.TableKey]dax.PartitionNums, to map[dax.TableKey]dax.PartitionNums) map[dax.TableKey]dax.PartitionNums {
if from == nil {
return to
}
added := make(map[dax.TableKey]dax.PartitionNums)
for tt, tps := range to {
fps, found := from[tt]
if !found {
added[tt] = tps
continue
}
addedPartitions := dax.PartitionNums{}
for i := range tps {
var found bool
for j := range fps {
if fps[j] == tps[i] {
found = true
break
}
}
if !found {
addedPartitions = append(addedPartitions, tps[i])
}
}
if len(addedPartitions) > 0 {
added[tt] = addedPartitions
}
}
return added
}
// fieldsComparer is used to compare the differences between two maps of
// table:[]fieldVersion.
type fieldsComparer struct {
from map[dax.TableKey][]dax.FieldName
to map[dax.TableKey][]dax.FieldName
}
func newFieldsComparer(from map[dax.TableKey][]dax.FieldName, to map[dax.TableKey][]dax.FieldName) *fieldsComparer {
return &fieldsComparer{
from: from,
to: to,
}
}
// added returns the fields which are present in `to` but not in `from`. The
// results remain in the format of a map of table:[]field.
func (f *fieldsComparer) added() map[dax.TableKey][]dax.FieldName {
return fieldsAdded(f.from, f.to)
}
// removed returns the fields which are present in `from` but not in `to`.
// The results remain in the format of a map of table:[]field.
func (f *fieldsComparer) removed() map[dax.TableKey][]dax.FieldName {
return fieldsAdded(f.to, f.from)
}
// fieldsAdded returns the fields which are present in `to` but not in `from`.
func fieldsAdded(from map[dax.TableKey][]dax.FieldName, to map[dax.TableKey][]dax.FieldName) map[dax.TableKey][]dax.FieldName {
if from == nil {
return to
}
added := make(map[dax.TableKey][]dax.FieldName)
for tt, tps := range to {
fps, found := from[tt]
if !found {
added[tt] = tps
continue
}
addedFieldVersions := []dax.FieldName{}
for i := range tps {
var found bool
for j := range fps {
if fps[j] == tps[i] {
found = true
break
}
}
if !found {
addedFieldVersions = append(addedFieldVersions, tps[i])
}
}
if len(addedFieldVersions) > 0 {
added[tt] = addedFieldVersions
}
}
return added
}
// shardsComparer is used to compare the differences between two maps of
// table:[]shardV.
type shardsComparer struct {
from map[dax.TableKey]dax.ShardNums
to map[dax.TableKey]dax.ShardNums
}
func newShardsComparer(from map[dax.TableKey]dax.ShardNums, to map[dax.TableKey]dax.ShardNums) *shardsComparer {
return &shardsComparer{
from: from,
to: to,
}
}
// added returns the shards which are present in `to` but not in `from`. The
// results remain in the format of a map of table:[]shard.
func (s *shardsComparer) added() map[dax.TableKey]dax.ShardNums {
return shardsAdded(s.from, s.to)
}
// removed returns the shards which are present in `from` but not in `to`. The
// results remain in the format of a map of table:[]shard.
func (s *shardsComparer) removed() map[dax.TableKey]dax.ShardNums {
return shardsAdded(s.to, s.from)
}
// shardsAdded returns the shards which are present in `to` but not in `from`.
func shardsAdded(from map[dax.TableKey]dax.ShardNums, to map[dax.TableKey]dax.ShardNums) map[dax.TableKey]dax.ShardNums {
if from == nil {
return to
}
added := make(map[dax.TableKey]dax.ShardNums)
for tt, tss := range to {
fss, found := from[tt]
if !found {
added[tt] = tss
continue
}
addedShards := dax.ShardNums{}
for i := range tss {
var found bool
for j := range fss {
if fss[j] == tss[i] {
found = true
break
}
}
if !found {
addedShards = append(addedShards, tss[i])
}
}
if len(addedShards) > 0 {
added[tt] = addedShards
}
}
return added
}
// createTableAndFields creates the FeatureBase Tables and Fields provided in
// the dax.Directive format.
func (api *API) createTableAndFields(tbl *dax.QualifiedTable, partitions dax.PartitionNums) error {
cim := &CreateIndexMessage{
Index: string(tbl.Key()),
CreatedAt: 0,
Meta: IndexOptions{
Keys: tbl.StringKeys(),
TrackExistence: true,
},
}
// Create the index in etcd as the system of record.
if err := api.holder.persistIndex(context.Background(), cim); err != nil {
return errors.Wrap(err, "persisting index")
}
idx, err := api.holder.createIndexWithPartitions(cim, partitions)
if err != nil {
return errors.Wrapf(err, "adding index: %s", tbl.Name)
}
// Add the fields
for _, fld := range tbl.Fields {
if fld.IsPrimaryKey() {
continue
}
if err := createField(idx, fld); err != nil {
return errors.Wrapf(err, "creating field: %s", fld.Name)
}
}
return nil
}
// createField creates a FeatureBase Field in the provided FeatureBase Index
// based on the provided field's type.
func createField(idx *Index, fld *dax.Field) error {
opts, err := FieldOptionsFromField(fld)
if err != nil {
return errors.Wrapf(err, "creating field options from field: %s", fld.Name)
}
if _, err := idx.createNullableField(string(fld.Name), "", opts...); err != nil {
return errors.Wrapf(err, "creating field on index: %s", fld.Name)
}
return nil
}

View file

@ -0,0 +1,25 @@
package pilosa
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestThingsAddedGeneric(t *testing.T) {
from := []string{"a", "b", "c"}
to := []string{"b", "c", "d"}
added := thingsAdded(from, to)
assert.Equal(t, added, []string{"d"})
}
func TestSliceComparer(t *testing.T) {
from := []string{"a", "b", "c"}
to := []string{"b", "c", "d"}
sc := newSliceComparer(from, to)
added := sc.added()
assert.Equal(t, added, []string{"d"})
}

97
api_directive_test.go Normal file
View file

@ -0,0 +1,97 @@
package pilosa_test
import (
"context"
"testing"
pilosa "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/dax"
daxtest "github.com/featurebasedb/featurebase/v3/dax/test"
"github.com/featurebasedb/featurebase/v3/test"
"github.com/stretchr/testify/assert"
)
// Ensure holder can handle an incoming directive.
func TestAPI_Directive(t *testing.T) {
c := test.MustRunCluster(t, 1)
defer c.Close()
api := c.GetPrimary().API
ctx := context.Background()
qdbid := dax.NewQualifiedDatabaseID("acme", "db1")
tbl1 := daxtest.TestQualifiedTableWithID(t, qdbid, "1", "tbl1", 12, false)
tbl2 := daxtest.TestQualifiedTableWithID(t, qdbid, "2", "tbl2", 12, false)
tbl3 := daxtest.TestQualifiedTableWithID(t, qdbid, "3", "tbl3", 12, false)
t.Run("Schema", func(t *testing.T) {
// Empty directive (and empty holder).
{
d := &dax.Directive{
Method: dax.DirectiveMethodFull,
Version: 1,
}
err := api.ApplyDirective(ctx, d)
assert.NoError(t, err)
assertTablesMatch(t, []string{}, api.Holder().Indexes())
}
// Add a new table.
{
d := &dax.Directive{
Method: dax.DirectiveMethodFull,
Tables: []*dax.QualifiedTable{
tbl1,
},
Version: 2,
}
err := api.ApplyDirective(ctx, d)
assert.NoError(t, err)
assertTablesMatch(t, []string{"tbl__acme__db1__1"}, api.Holder().Indexes())
}
// Add a new table, and keep the existing table.
{
d := &dax.Directive{
Method: dax.DirectiveMethodFull,
Tables: []*dax.QualifiedTable{
tbl1,
tbl2,
},
Version: 3,
}
err := api.ApplyDirective(ctx, d)
assert.NoError(t, err)
assertTablesMatch(t, []string{"tbl__acme__db1__1", "tbl__acme__db1__2"}, api.Holder().Indexes())
}
// Add a new table and remove one of the existing tables.
{
d := &dax.Directive{
Method: dax.DirectiveMethodFull,
Tables: []*dax.QualifiedTable{
tbl2,
tbl3,
},
Version: 4,
}
err := api.ApplyDirective(ctx, d)
assert.NoError(t, err)
assertTablesMatch(t, []string{"tbl__acme__db1__2", "tbl__acme__db1__3"}, api.Holder().Indexes())
}
})
}
// assertTablesMatch is a helper function which asserts that the list of index
// names in `actual` match those provided in `expected`.
func assertTablesMatch(t *testing.T, expected []string, actual []*pilosa.Index) {
t.Helper()
act := make([]string, len(actual))
for i := range actual {
act[i] = actual[i].Name()
}
assert.ElementsMatch(t, expected, act)
}

1588
api_test.go Normal file

File diff suppressed because it is too large Load diff

57
apimethod_string.go Normal file
View file

@ -0,0 +1,57 @@
// Code generated by "stringer -type=apiMethod"; DO NOT EDIT.
package pilosa
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[apiClusterMessage-0]
_ = x[apiCreateField-1]
_ = x[apiCreateIndex-2]
_ = x[apiDeleteField-3]
_ = x[apiDeleteAvailableShard-4]
_ = x[apiDeleteIndex-5]
_ = x[apiDeleteView-6]
_ = x[apiExportCSV-7]
_ = x[apiFragmentBlockData-8]
_ = x[apiFragmentBlocks-9]
_ = x[apiFragmentData-10]
_ = x[apiTranslateData-11]
_ = x[apiFieldTranslateData-12]
_ = x[apiField-13]
_ = x[apiImport-14]
_ = x[apiImportValue-15]
_ = x[apiIndex-16]
_ = x[apiQuery-17]
_ = x[apiRecalculateCaches-18]
_ = x[apiSchema-19]
_ = x[apiShardNodes-20]
_ = x[apiState-21]
_ = x[apiViews-22]
_ = x[apiApplySchema-23]
_ = x[apiStartTransaction-24]
_ = x[apiFinishTransaction-25]
_ = x[apiTransactions-26]
_ = x[apiGetTransaction-27]
_ = x[apiActiveQueries-28]
_ = x[apiPastQueries-29]
_ = x[apiIDReserve-30]
_ = x[apiIDCommit-31]
_ = x[apiIDReset-32]
_ = x[apiPartitionNodes-33]
_ = x[apiMutexCheck-34]
}
const _apiMethod_name = "apiClusterMessageapiCreateFieldapiCreateIndexapiDeleteFieldapiDeleteAvailableShardapiDeleteIndexapiDeleteViewapiExportCSVapiFragmentBlockDataapiFragmentBlocksapiFragmentDataapiTranslateDataapiFieldTranslateDataapiFieldapiImportapiImportValueapiIndexapiQueryapiRecalculateCachesapiSchemaapiShardNodesapiStateapiViewsapiApplySchemaapiStartTransactionapiFinishTransactionapiTransactionsapiGetTransactionapiActiveQueriesapiPastQueriesapiIDReserveapiIDCommitapiIDResetapiPartitionNodesapiMutexCheck"
var _apiMethod_index = [...]uint16{0, 17, 31, 45, 59, 82, 96, 109, 121, 141, 158, 173, 189, 210, 218, 227, 241, 249, 257, 277, 286, 299, 307, 315, 329, 348, 368, 383, 400, 416, 430, 442, 453, 463, 480, 493}
func (i apiMethod) String() string {
if i < 0 || i >= apiMethod(len(_apiMethod_index)-1) {
return "apiMethod(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _apiMethod_name[_apiMethod_index[i]:_apiMethod_index[i+1]]
}

686
apply.go Normal file
View file

@ -0,0 +1,686 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"sync"
"github.com/apache/arrow/go/v10/arrow"
"github.com/apache/arrow/go/v10/arrow/array"
"github.com/apache/arrow/go/v10/arrow/memory"
"github.com/featurebasedb/featurebase/v3/pql"
"github.com/featurebasedb/featurebase/v3/tracing"
"github.com/featurebasedb/featurebase/v3/vprint"
"github.com/gomem/gomem/pkg/dataframe"
"github.com/pkg/errors"
ivy "robpike.io/ivy/arrow"
config "robpike.io/ivy/config"
"robpike.io/ivy/exec"
"robpike.io/ivy/parse"
"robpike.io/ivy/run"
"robpike.io/ivy/scan"
"robpike.io/ivy/value"
)
type (
ApplyResult *arrow.Column
)
func runIvyString(context value.Context, str string) (ok bool, err error) {
defer func() {
if r := recover(); r != nil {
err = r.(value.Error)
}
}()
scanner := scan.New(context, "<args>", strings.NewReader(str))
parser := parse.NewParser("<args>", scanner, context)
ok = run.Run(parser, context, false)
return
}
// Possibly combine all arrays together then apply some interesting
// computation at the end?
func IvyReduce(reduceCode string, opCode string, opt *ExecOptions) (func(ctx context.Context, prev, v interface{}) interface{}, func() (*dataframe.DataFrame, error)) {
var accumulator value.Value
mu := &sync.Mutex{}
concat := value.BinaryOps[opCode]
conf := getDefaultConfig()
ctxIvy := exec.NewContext(&conf)
// concat returned results at coordinating node.
reduceFn := func(ctx context.Context, prev, v interface{}) interface{} {
if v == nil {
return prev
}
if accumulator == nil {
switch val := v.(type) {
case *dataframe.DataFrame:
col := val.ColumnAt(0)
resolver := dataframe.NewChunkResolver(col)
accumulator = value.NewArrowVector(col, &conf, &resolver)
case value.Value:
accumulator = v.(value.Value)
default:
return errors.New(fmt.Sprintf("ivy reduction failed first unexpected type %T", v))
}
return nil
}
switch val := v.(type) {
case *dataframe.DataFrame:
col := val.ColumnAt(0)
resolver := dataframe.NewChunkResolver(col)
x := value.NewArrowVector(col, &conf, &resolver)
mu.Lock() // i'm being overyerly cautious..need to confirm this can be concurrent
accumulator = concat.EvalBinary(ctxIvy, accumulator, x)
mu.Unlock()
case value.Value:
mu.Lock()
accumulator = concat.EvalBinary(ctxIvy, accumulator, val)
mu.Unlock()
default:
return errors.New(fmt.Sprintf("ivy reduction failed unexpected type %T", v))
}
return nil
}
tablerFn := func() (*dataframe.DataFrame, error) {
pool := memory.NewGoAllocator() // TODO(twg) 2022/09/01 singledton?
if opt.Remote {
col := value.ToArrowColumn(accumulator, pool)
return dataframe.NewDataFrameFromColumns(pool, []arrow.Column{*col})
}
// only actually reduce on the initiating node i hate the network
// over head but oh well
ctxIvy.AssignGlobal("_", accumulator)
ok, err := runIvyString(ctxIvy, reduceCode)
if err != nil {
return nil, err
}
if ok {
v := ctxIvy.Global("_")
if v == nil {
return nil, errors.New("ivy reduction no result ")
}
col := value.ToArrowColumn(ctxIvy.Global("_"), pool)
return dataframe.NewDataFrameFromColumns(pool, []arrow.Column{*col})
}
return nil, errors.New("ivy reduction failed ")
}
return reduceFn, tablerFn
}
// executeApply executes a Apply() call.
func (e *executor) executeApply(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *ExecOptions) (*dataframe.DataFrame, error) {
if !e.dataframeEnabled {
return nil, errors.New("Dataframe support not enabled")
}
span, ctx := tracing.StartSpanFromContext(ctx, "Executor.executeMax")
defer span.Finish()
if _, err := c.FirstStringArg("_ivy"); err != nil {
return nil, errors.Wrap(err, " no ivy program supplied")
}
if len(c.Children) > 1 {
return nil, errors.New("Apply() only accepts a single bitmap input filter")
}
// Execute calls in bulk on each remote node and merge.
mapFn := func(ctx context.Context, shard uint64, mopt *mapOptions) (_ interface{}, err error) {
return e.executeApplyShard(ctx, qcx, index, c, shard)
}
ivyReduce, ok, err := c.StringArg("_ivyReduce")
if err != nil {
return nil, err
}
reduceFn, tablerFn := IvyReduce("_", ",", opt)
if ok {
reduceFn, tablerFn = IvyReduce(ivyReduce, ",", opt)
}
_, err = e.mapReduce(ctx, index, shards, c, opt, mapFn, reduceFn)
if err != nil {
return nil, err
}
return tablerFn()
}
func getDefaultConfig() config.Config {
maxbits := uint(1e9) // "maximum size of an integer, in bits; 0 means no limit")
maxdigits := uint(1e4) // "above this many `digits`, integers print as floating point; 0 disables")
maxstack := uint(100000)
origin := 1 // "set index origin to `n` (must be 0 or 1)")
prompt := "" // flag.String("prompt", "", "command `prompt`")
format := ""
// debugFlag := "" // flag.String("debug", "", "comma-separated `names` of debug settings to enable")
conf := config.Config{}
conf.SetFormat(format)
conf.SetMaxBits(maxbits)
conf.SetMaxDigits(maxdigits)
conf.SetMaxStack(maxstack)
conf.SetOrigin(origin)
conf.SetPrompt(prompt)
conf.SetOutput(io.Discard)
conf.SetErrOutput(io.Discard)
conf.SetEmbedded(true) // needed to propagate panic
return conf
}
func filterDataframe(resolver dataframe.Resolver, pool memory.Allocator, filter []int64) (*dataframe.IndexResolver, error) {
if resolver.NumRows() == 0 {
return nil, errors.New("No data")
}
indexResolver := dataframe.NewIndexResolver(len(filter), uint32(ShardWidth-1))
for i, id := range filter {
if int(id) >= resolver.NumRows() {
continue
}
c, o := resolver.Resolve(int(id))
indexResolver.Set(i, c, o)
}
return indexResolver, nil
}
func (e *executor) executeApplyShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64) (value.Value, error) {
span, _ := tracing.StartSpanFromContext(ctx, "Executor.executeApplyShard")
defer span.Finish()
ivyProgram, ok, err := c.StringArg("_ivy")
if err != nil || !ok {
return nil, errors.Wrap(err, "finding ivy program")
}
var filter *Row
if len(c.Children) == 1 {
row, err := e.executeBitmapCallShard(ctx, qcx, index, c.Children[0], shard)
if err != nil {
return nil, err
}
filter = row
if !filter.Any() {
// no need to actuall run the query for its not operating against any values
return value.NewVector([]value.Value{}), nil
}
}
//
pool := memory.NewGoAllocator() // TODO(twg) 2022/09/01 singledton?
ids := filter.ShardColumns() // needs to be shard columns
// Fetch index.
idx := e.Holder.Index(index)
if idx == nil {
return nil, newNotFoundError(ErrIndexNotFound, index)
}
fname := idx.GetDataFramePath(shard)
if !e.dataFrameExists(fname) {
return value.NewVector([]value.Value{}), nil
}
table, err := e.getDataTable(ctx, fname, pool)
if err != nil {
return nil, err
}
defer table.Release()
df, err := dataframe.NewDataFrameFromTable(pool, table)
if err != nil {
return nil, err
}
p := dataframe.NewChunkResolver(df.ColumnAt(0))
var resolver dataframe.Resolver
resolver = &p
if filter != nil {
if len(ids) == 0 {
return value.NewVector([]value.Value{}), nil
}
resolver, err = filterDataframe(resolver, pool, ids)
if err != nil {
return nil, err
}
}
conf := getDefaultConfig()
context, err := ivy.RunArrow(dataframe.NewTableFacade(df), ivyProgram, conf, resolver)
if err != nil {
return nil, fmt.Errorf("ivy map error: %w", err)
}
return context.Global("_"), nil
}
// ///////////////////////////////////////////////////////
// all the ingest supporting functions
// ///////////////////////////////////////////////////////
func NewShardFile(ctx context.Context, name string, mem memory.Allocator, e *executor) (*ShardFile, error) {
if !e.dataFrameExists(name) {
return &ShardFile{dest: name, executor: e, strings: make(map[key][]string)}, nil
}
// else read in existing
table, err := e.getDataTable(ctx, name, mem)
if err != nil {
return nil, err
}
return &ShardFile{table: table, schema: table.Schema(), dest: name, executor: e, strings: make(map[key][]string)}, nil
}
type NameType struct {
Name string
DataType arrow.DataType
}
type ChangesetRequest struct {
ShardIds []int64 // only shardwidth bits to provide 0 indexing inside shard file
Columns []interface{}
SimpleSchema []NameType
}
// TODO(twg) 2022/09/30 Needs a refactor
func cast(v interface{}) arrow.DataType {
switch v.(type) {
case *arrow.Int64Type:
return arrow.PrimitiveTypes.Int64
case int64:
return arrow.PrimitiveTypes.Int64
case *arrow.Float64Type:
return arrow.PrimitiveTypes.Float64
case float64:
return arrow.PrimitiveTypes.Float64
case *arrow.StringType:
return arrow.BinaryTypes.String
default:
vprint.VV("%T .... %v", v, v)
}
return arrow.PrimitiveTypes.Int64
}
func (cr *ChangesetRequest) ArrowSchema() *arrow.Schema {
fields := make([]arrow.Field, len(cr.SimpleSchema))
for i := range cr.SimpleSchema {
fields[i] = arrow.Field{Name: cr.SimpleSchema[i].Name, Type: cast(cr.SimpleSchema[i].DataType)}
}
return arrow.NewSchema(fields, nil)
}
type key struct {
col int
chunk int
}
type ShardFile struct {
table arrow.Table
schema *arrow.Schema
beforeRows int64
added int64
columns []interface{}
dest string
executor *executor
strings map[key][]string
}
func compareSchema(s1, s2 *arrow.Schema) bool {
if s1 == nil || s2 == nil {
return false
}
if len(s1.Fields()) != len(s2.Fields()) {
return false
}
for i := 0; i < len(s1.Fields()); i++ {
f1 := s1.Field(i)
f2 := s2.Field(i)
if f1.Name != f2.Name {
return false
}
if f1.Type != f2.Type {
return false
}
}
return true
}
func (sf *ShardFile) EnsureSchema(cs *ChangesetRequest) error {
schema := cs.ArrowSchema()
if sf.schema == nil {
sf.schema = schema
} else {
if !compareSchema(sf.schema, schema) {
vprint.VV("incomeing schema", schema)
vprint.VV("existing schema", sf.schema)
return errors.New("dataframe schema's don't match")
}
}
sf.columns = make([]interface{}, len(sf.schema.Fields()))
return nil
}
func (sf *ShardFile) buildAppenders(maxid int64) {
if sf.table != nil {
sf.beforeRows = sf.table.NumRows()
}
if maxid < sf.beforeRows {
// no need to add new rows
return
}
newSize := maxid - sf.beforeRows + 1
for i := 0; i < len(sf.schema.Fields()); i++ {
switch sf.schema.Field(i).Type {
case arrow.PrimitiveTypes.Int64:
sf.columns[i] = make([]int64, newSize)
case arrow.PrimitiveTypes.Float64:
sf.columns[i] = make([]float64, newSize)
case arrow.BinaryTypes.String:
sf.columns[i] = make([]string, newSize)
}
}
sf.added = newSize
}
// the row offset must be reset to 0 for the slices being appended
func (sf *ShardFile) SetIntValue(col int, row int64, val int64) {
v := sf.columns[col].([]int64)
v[row-sf.beforeRows] = val
}
func (sf *ShardFile) SetFloatValue(col int, row int64, val float64) {
v := sf.columns[col].([]float64)
v[row-sf.beforeRows] = val
}
func (sf *ShardFile) SetStringValue(col int, row int64, val string) {
v := sf.columns[col].([]string)
v[row-sf.beforeRows] = val
}
func (sf *ShardFile) Process(cs *ChangesetRequest) error {
err := sf.process(cs)
if err != nil {
return err
}
rtemp := sf.dest + ".temp"
err = sf.Save(rtemp)
if err != nil {
return err
}
return os.Rename(rtemp+sf.executor.TableExtension(), sf.dest+sf.executor.TableExtension())
}
func (sf *ShardFile) LoadBlobs() error {
for col := 0; col < len(sf.schema.Fields()); col++ {
column := sf.table.Column(col)
switch column.DataType() {
case arrow.BinaryTypes.String:
for i, chunk := range column.Data().Chunks() {
stringData := chunk.(*array.String)
k := key{col: col, chunk: i}
for j := 0; j < stringData.Len(); j++ {
v := stringData.Value(j)
sf.strings[k] = append(sf.strings[k], v)
}
}
}
}
return nil
}
func (sf *ShardFile) ReplaceString(col, chunk, l int, s string) {
sf.strings[key{col: col, chunk: chunk}][l] = s
}
func (sf *ShardFile) process(cs *ChangesetRequest) error {
offset := 0
if sf.table != nil {
// need to load blobs prior
sf.LoadBlobs()
column := sf.table.Column(0)
resolver := dataframe.NewChunkResolver(column)
for i, rowid := range cs.ShardIds {
offset = i
if rowid >= sf.table.NumRows() {
break
}
chunk, l := resolver.Resolve(int(rowid))
for col := 0; col < len(sf.schema.Fields()); col++ {
column := sf.table.Column(col)
switch column.DataType() {
case arrow.PrimitiveTypes.Int64:
v := column.Data().Chunk(chunk).(*array.Int64).Int64Values()
v[l] = cs.Columns[col].([]int64)[i]
case arrow.PrimitiveTypes.Float64:
v := column.Data().Chunk(chunk).(*array.Float64).Float64Values()
v[l] = cs.Columns[col].([]float64)[i]
case arrow.BinaryTypes.String:
// TODO(twg) 2023/01/09 How to update existing?
new := cs.Columns[col].([]string)[i]
sf.ReplaceString(col, chunk, l, new)
default:
panic(fmt.Sprintf("Unknown Type %v", column.DataType()))
}
}
}
}
max := cs.ShardIds[len(cs.ShardIds)-1]
sf.buildAppenders(max)
// need to check if only replace and no apend
if sf.added > 0 {
for i, rowid := range cs.ShardIds[offset:] {
i += offset
for col := 0; col < len(sf.schema.Fields()); col++ {
switch sf.schema.Field(col).Type {
case arrow.PrimitiveTypes.Int64:
sf.SetIntValue(col, rowid, cs.Columns[col].([]int64)[i])
case arrow.PrimitiveTypes.Float64:
sf.SetFloatValue(col, rowid, cs.Columns[col].([]float64)[i])
case arrow.BinaryTypes.String:
sf.SetStringValue(col, rowid, cs.Columns[col].([]string)[i])
default:
panic(fmt.Sprintf("2 Unknown Type %v", sf.schema.Field(col).Type))
}
}
}
}
return nil
}
type twoSlices struct {
id_slice []int
lists_slice [][]string
}
type SortByOther twoSlices
func (sbo SortByOther) Len() int {
return len(sbo.id_slice)
}
func (sbo SortByOther) Swap(i, j int) {
sbo.id_slice[i], sbo.id_slice[j] = sbo.id_slice[j], sbo.id_slice[i]
sbo.lists_slice[i], sbo.lists_slice[j] = sbo.lists_slice[j], sbo.lists_slice[i]
}
func (sbo SortByOther) Less(i, j int) bool {
return sbo.id_slice[i] < sbo.id_slice[j]
}
func (sf *ShardFile) buildFromStrings(idx int, mem memory.Allocator) []arrow.Array {
ids := make([]int, 0)
lists := make([][]string, 0)
for k, v := range sf.strings {
if k.col == idx { // ugh not ordered :(
ids = append(ids, k.chunk)
lists = append(lists, v)
}
}
// sort ids/lists
parts := twoSlices{id_slice: ids, lists_slice: lists}
sort.Sort(SortByOther(parts))
builder := array.NewStringBuilder(mem)
chunks := make([]arrow.Array, 0)
for _, v := range parts.lists_slice {
builder.AppendValues(v, nil)
newChunk := builder.NewArray()
chunks = append(chunks, newChunk)
}
return chunks
}
func (sf *ShardFile) Save(name string) error {
parts := make([]arrow.Array, 0)
mem := memory.NewGoAllocator()
for col := 0; col < len(sf.schema.Fields()); col++ {
chunks := make([]arrow.Array, 0)
if sf.table != nil {
// we append if there was existing file
column := sf.table.Column(col)
// if primitive type
switch column.DataType() {
case arrow.BinaryTypes.String:
chunks = sf.buildFromStrings(col, mem)
default:
chunks = append(chunks, column.Data().Chunks()...)
}
// else binary type
}
switch sf.schema.Field(col).Type {
case arrow.PrimitiveTypes.Int64:
// case *arrow.Int64Type:
if sf.added > 0 {
ibuild := array.NewInt64Builder(mem)
ibuild.AppendValues(sf.columns[col].([]int64), nil) // TODO(twg) 2022/09/28 need to handle null
newChunk := ibuild.NewArray()
chunks = append(chunks, newChunk)
}
record, err := array.Concatenate(chunks, mem)
if err != nil {
return err
}
parts = append(parts, record)
case arrow.PrimitiveTypes.Float64:
// case *arrow.Float64Type:
if sf.added > 0 {
fbuild := array.NewFloat64Builder(mem)
fbuild.AppendValues(sf.columns[col].([]float64), nil) // TODO(twg) 2022/09/28 need to handle null
newChunk := fbuild.NewArray()
chunks = append(chunks, newChunk)
}
record, err := array.Concatenate(chunks, mem)
if err != nil {
return err
}
parts = append(parts, record)
case arrow.BinaryTypes.String:
if sf.added > 0 {
fbuild := array.NewStringBuilder(mem)
fbuild.AppendValues(sf.columns[col].([]string), nil) // TODO(twg) 2022/09/28 need to handle null
newChunk := fbuild.NewArray()
chunks = append(chunks, newChunk)
}
record, err := array.Concatenate(chunks, mem)
if err != nil {
return err
}
parts = append(parts, record)
default:
vprint.VV("UNKNOWN %T", sf.schema.Field(col).Type)
}
}
rec := array.NewRecord(sf.schema, parts, sf.beforeRows+sf.added)
table := array.NewTableFromRecords(sf.schema, []arrow.Record{rec})
return sf.executor.SaveTable(name, table, mem)
}
// TODO(twg) 2022/10/03 Not a huge fan of the global variable will look at adding to executor structure
// when dataframe is fully integrated
var (
dataframeShardLocks map[uint64]*sync.Mutex
muWriteDataframe sync.Mutex
)
func init() {
dataframeShardLocks = make(map[uint64]*sync.Mutex)
}
func getDataframeWritelock(shard uint64) *sync.Mutex {
muWriteDataframe.Lock()
defer muWriteDataframe.Unlock()
lock, ok := dataframeShardLocks[shard]
if ok {
return lock
}
newLock := sync.Mutex{}
dataframeShardLocks[shard] = &newLock
return &newLock
}
func (api *API) ApplyDataframeChangeset(ctx context.Context, index string, cs *ChangesetRequest, shard uint64) error {
// TODO(twg) 2022/09/29 need to validate api call
idx := api.Holder().Index(index)
// check if dataframe exists
fname := idx.GetDataFramePath(shard)
// only 1 shard writer allowed at at time so wait for it to be available
mu := getDataframeWritelock(shard)
mu.Lock()
defer mu.Unlock()
mem := memory.NewGoAllocator()
shardFile, err := NewShardFile(ctx, fname, mem, api.server.executor)
if err != nil {
return err
}
err = shardFile.EnsureSchema(cs)
if err != nil {
return err
}
return shardFile.Process(cs)
}
type column struct {
Name string
Type string
}
func (api *API) GetDataframeSchema(ctx context.Context, indexName string) (interface{}, error) {
idx, err := api.Index(ctx, indexName)
if err != nil {
return nil, err
}
base := idx.DataframesPath()
dir, _ := os.Open(base)
files, _ := dir.Readdir(0)
parts := make([]column, 0)
mem := memory.NewGoAllocator()
for i := range files {
file := files[i]
name := file.Name()
if api.server.executor.IsDataframeFile(name) {
// strip off the parquet extenison
name = strings.TrimSuffix(name, filepath.Ext(name))
// read the parquet file and extract the schema
fname := filepath.Join(base, name)
table, err := api.server.executor.getDataTable(ctx, fname, mem)
if err != nil {
return nil, err
}
for i := 0; i < int(table.NumCols()); i++ {
col := table.Column(i)
part := column{Name: col.Name(), Type: col.DataType().String()}
parts = append(parts, part)
}
break // only go on first file
}
}
return parts, nil
}

562
arrow.go Normal file
View file

@ -0,0 +1,562 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"sync"
"github.com/apache/arrow/go/v10/arrow"
"github.com/apache/arrow/go/v10/arrow/array"
"github.com/apache/arrow/go/v10/arrow/ipc"
"github.com/apache/arrow/go/v10/arrow/memory"
"github.com/apache/arrow/go/v10/parquet"
"github.com/apache/arrow/go/v10/parquet/file"
"github.com/apache/arrow/go/v10/parquet/pqarrow"
"github.com/featurebasedb/featurebase/v3/pql"
"github.com/featurebasedb/featurebase/v3/tracing"
"github.com/gomem/gomem/pkg/dataframe"
"github.com/pkg/errors"
)
/*
The function Arrow provides filtered access to the raw values stored in the dataframe.
If Arrow is just provided a bitmap filter, such as ConstRow or any Bitmap Operation,
all the values associated with each column are returned. This set can be limited with
the addition of the header parameter
Example:
Arrow(ConstRow(columns=[2,4,6]),header=["fval"])
*/
// executeApply executes a Arrow() call.
func (e *executor) executeArrow(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *ExecOptions) (arrow.Table, error) {
if !e.dataframeEnabled {
return nil, errors.New("Dataframe support not enabled")
}
span, ctx := tracing.StartSpanFromContext(ctx, "Executor.executeArrow")
defer span.Finish()
if len(c.Children) > 1 {
return nil, errors.New("Apply() only accepts a single bitmap input filter")
}
var columnFilter []string
if cols, ok := c.Args["header"].([]interface{}); ok {
columnFilter = make([]string, 0, len(cols))
for _, v := range cols {
columnFilter = append(columnFilter, v.(string))
}
}
mapcounter := 0
reducecounter := 0
pool := memory.NewGoAllocator() // TODO(twg) 2022/09/01 singledton?
// Execute calls in bulk on each remote node and merge.
mu := &sync.Mutex{}
mapFn := func(ctx context.Context, shard uint64, mopt *mapOptions) (_ interface{}, err error) {
mu.Lock()
mapcounter++
mu.Unlock()
return e.executeArrowShard(ctx, qcx, index, c, shard, pool, columnFilter)
}
tables := make([]*BasicTable, 0)
reduceFn := func(ctx context.Context, prev, v interface{}) interface{} {
mu.Lock()
reducecounter++
mu.Unlock()
if v == nil {
return prev
}
switch t := v.(type) {
case *BasicTable:
if t.resolver != nil {
mu.Lock()
tables = append(tables, t)
mu.Unlock()
}
case arrow.Table:
if t.NumRows() > 0 {
bt := BasicTableFromArrow(t, pool)
mu.Lock()
tables = append(tables, bt)
mu.Unlock()
}
}
return nil
}
_, err := e.mapReduce(ctx, index, shards, c, opt, mapFn, reduceFn)
if err != nil {
return nil, err
}
if len(tables) == 0 {
return &BasicTable{name: "empty"}, nil
}
tbl := Concat(tables[0].Schema(), tables, pool)
r := dataframe.NewChunkResolver(tbl.Column(0))
return &BasicTable{resolver: &r, table: tbl}, nil
}
type BasicTable struct {
resolver dataframe.Resolver
table arrow.Table
filtered bool
name string
}
func (st *BasicTable) Name() string {
return st.name
}
func (st *BasicTable) Schema() *arrow.Schema {
if st.table != nil {
return st.table.Schema()
}
return &arrow.Schema{}
}
func (st *BasicTable) IsFiltered() bool {
return st.filtered
}
func (st *BasicTable) NumRows() int64 {
if st.resolver == nil {
return 0
}
return int64(st.resolver.NumRows())
}
func (st *BasicTable) NumCols() int64 {
if st.table != nil {
return st.table.NumCols()
}
return 0
}
func (st *BasicTable) Column(i int) *arrow.Column {
if st.table != nil {
return st.table.Column(i)
}
return nil
}
func (st *BasicTable) Retain() {
if st.table != nil {
st.table.Retain()
}
}
func (st *BasicTable) Release() {
if st.table != nil {
st.table.Retain()
}
}
func (st *BasicTable) Get(column, row int) interface{} {
field := st.Schema().Field(column)
c, i := st.resolver.Resolve(row)
nullable := field.Nullable
chunk := st.Column(column).Data().Chunk(c)
// TODO(twg) 2023/01/26 potential NULL support?
if nullable && chunk.IsNull(i) {
return nil
}
switch field.Type.(type) {
case *arrow.BooleanType:
return chunk.(*array.Boolean).Value(i)
case *arrow.Int8Type:
v := chunk.(*array.Int8).Int8Values()
return int64(v[i])
case *arrow.Int16Type:
v := chunk.(*array.Int16).Int16Values()
return int64(v[i])
case *arrow.Int32Type:
v := chunk.(*array.Int32).Int32Values()
return int64(v[i])
case *arrow.Int64Type:
v := chunk.(*array.Int64).Int64Values()
return int64(v[i])
case *arrow.Uint8Type:
v := chunk.(*array.Uint8).Uint8Values()
return uint64(v[i])
case *arrow.Uint16Type:
v := chunk.(*array.Uint16).Uint16Values()
return uint64(v[i])
case *arrow.Uint32Type:
v := chunk.(*array.Uint32).Uint32Values()
return uint64(v[i])
case *arrow.Uint64Type:
v := chunk.(*array.Uint64).Uint64Values()
return v[i]
case *arrow.Float32Type:
v := chunk.(*array.Float32).Float32Values()
return float64(v[i])
case *arrow.Float64Type:
v := chunk.(*array.Float64).Float64Values()
return v[i]
case *arrow.StringType:
return chunk.(*array.String).Value(i)
}
return 0
}
func builderFrom(mem memory.Allocator, dt arrow.DataType, size int64) array.Builder {
var bldr array.Builder
switch dt := dt.(type) {
case *arrow.BooleanType:
bldr = array.NewBooleanBuilder(mem)
case *arrow.Int8Type:
bldr = array.NewInt8Builder(mem)
case *arrow.Int16Type:
bldr = array.NewInt16Builder(mem)
case *arrow.Int32Type:
bldr = array.NewInt32Builder(mem)
case *arrow.Int64Type:
bldr = array.NewInt64Builder(mem)
case *arrow.Uint8Type:
bldr = array.NewUint8Builder(mem)
case *arrow.Uint16Type:
bldr = array.NewUint16Builder(mem)
case *arrow.Uint32Type:
bldr = array.NewUint32Builder(mem)
case *arrow.Uint64Type:
bldr = array.NewUint64Builder(mem)
case *arrow.Float32Type:
bldr = array.NewFloat32Builder(mem)
case *arrow.Float64Type:
bldr = array.NewFloat64Builder(mem)
case *arrow.StringType:
bldr = array.NewStringBuilder(mem)
default:
panic(fmt.Errorf("builderFrom: invalid Arrow type %v", dt))
}
bldr.Reserve(int(size))
return bldr
}
func appendData(bldr array.Builder, v interface{}) {
switch bldr := bldr.(type) {
case *array.BooleanBuilder:
bldr.Append(v.(bool))
case *array.Int8Builder:
bldr.Append(v.(int8))
case *array.Int16Builder:
bldr.Append(v.(int16))
case *array.Int32Builder:
bldr.Append(v.(int32))
case *array.Int64Builder:
bldr.Append(v.(int64))
case *array.Uint8Builder:
bldr.Append(v.(uint8))
case *array.Uint16Builder:
bldr.Append(v.(uint16))
case *array.Uint32Builder:
bldr.Append(v.(uint32))
case *array.Uint64Builder:
bldr.Append(v.(uint64))
case *array.Float32Builder:
bldr.Append(v.(float32))
case *array.Float64Builder:
bldr.Append(v.(float64))
case *array.StringBuilder:
bldr.Append(v.(string))
default:
panic(fmt.Errorf("appendData: invalid Arrow builder type %T", bldr))
}
}
func Concat(schema *arrow.Schema, tables []*BasicTable, mem memory.Allocator) arrow.Table {
if len(tables) == 1 {
if !tables[0].IsFiltered() {
return tables[0]
}
}
cols := make([]arrow.Column, len(schema.Fields()))
defer func(cols []arrow.Column) {
for i := range cols {
cols[i].Release()
}
}(cols)
sz := 0
for i := range tables {
sz += int(tables[i].NumRows())
}
for i := range cols {
field := schema.Field(i)
arrs := make([]arrow.Array, 0)
builder := builderFrom(mem, field.Type, int64(sz))
for t := range tables {
table := tables[t]
if table.IsFiltered() {
for row := 0; row < int(table.NumRows()); row++ {
v := table.Get(i, row)
appendData(builder, v)
}
arrs = append(arrs, builder.NewArray())
} else {
parts := table.Column(i).Data()
arrs = append(arrs, parts.Chunks()...)
}
}
chunk := arrow.NewChunked(field.Type, arrs)
cols[i] = *arrow.NewColumn(field, chunk)
chunk.Release()
}
return array.NewTable(schema, cols, -1)
}
func (st *BasicTable) MarshalJSON() ([]byte, error) {
results := make(map[string]interface{})
n := 0
if st.table != nil {
n = int(st.table.NumCols())
}
for b := 0; b < n; b++ {
col := st.table.Column(b)
result := make([]interface{}, st.resolver.NumRows())
for n := st.resolver.NumRows() - 1; n >= 0; n-- {
v := st.Get(b, n)
result[n] = v
}
results[col.Name()] = result
}
return json.Marshal(results)
}
func BasicTableFromArrow(table arrow.Table, mem memory.Allocator) *BasicTable {
col := table.Column(0)
r := dataframe.NewChunkResolver(col)
return &BasicTable{resolver: &r, table: table}
}
func filterColumns(filters []string, table arrow.Table) arrow.Table {
filters = append(filters, "_ID")
schema := table.Schema()
// TODO(twg) 2022/11/09 add glob support
allFields := schema.Fields()
in := func(key string) bool {
for _, v := range filters {
if v == key {
return true
}
}
return false
}
cols := make([]arrow.Column, 0)
fields := make([]arrow.Field, 0)
for i := range allFields {
field := allFields[i]
if in(field.Name) {
cols = append(cols, *table.Column(i))
fields = append(fields, field)
}
}
filterdSchema := arrow.NewSchema(fields, nil) // TODO(twg) 2022/11/09 handle meta:w
return array.NewTable(filterdSchema, cols, table.NumRows())
}
func (e *executor) executeArrowShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64, pool memory.Allocator, columnFilter []string) (*BasicTable, error) {
name := fmt.Sprintf("a. %v", shard)
span, _ := tracing.StartSpanFromContext(ctx, "Executor.executeArrowShard")
defer span.Finish()
var filter *Row
if len(c.Children) == 1 {
row, err := e.executeBitmapCallShard(ctx, qcx, index, c.Children[0], shard)
if err != nil {
return nil, err
}
filter = row
if !filter.Any() {
// no need to actuall run the query for its not operating against any values
return &BasicTable{name: name}, nil
}
}
//
ids := filter.ShardColumns() // needs to be shard columns
// Fetch index.
idx := e.Holder.Index(index)
if idx == nil {
return nil, newNotFoundError(ErrIndexNotFound, index)
}
fname := idx.GetDataFramePath(shard)
if !e.dataFrameExists(fname) {
return &BasicTable{name: name}, nil
}
table, err := e.getDataTable(ctx, fname, pool)
if err != nil {
return nil, errors.Wrap(err, "arrow readTableParquet")
}
defer table.Release()
if len(columnFilter) > 0 {
table = filterColumns(columnFilter, table)
}
df, err := dataframe.NewDataFrameFromTable(pool, table)
if err != nil {
return nil, errors.Wrap(err, "arrow NewDataFromTable")
}
p := dataframe.NewChunkResolver(df.ColumnAt(0))
var resolver dataframe.Resolver
resolver = &p
if filter != nil {
if len(ids) == 0 {
return &BasicTable{name: name}, nil
}
resolver, err = filterDataframe(resolver, pool, ids)
if err != nil {
return nil, errors.Wrap(err, "filtering dataframe")
}
}
table.Retain()
return &BasicTable{resolver: resolver, table: table, filtered: filter != nil, name: name}, nil
}
func (e *executor) dataFrameExists(fname string) bool {
if e.typeIsParquet() {
if _, err := os.Stat(fname + ".parquet"); os.IsNotExist(err) {
return false
}
return true
}
if _, err := os.Stat(fname + ".arrow"); os.IsNotExist(err) {
return false
}
return true
}
func (e *executor) getDataTable(ctx context.Context, fname string, mem memory.Allocator) (arrow.Table, error) {
if e.typeIsParquet() {
table, err := readTableParquetCtx(ctx, fname, mem)
return table, err
}
return readTableArrow(fname, mem)
}
func (e *executor) typeIsParquet() bool {
return e.datafameUseParquet
}
func (e *executor) IsDataframeFile(name string) bool {
if e.typeIsParquet() {
return strings.HasSuffix(name, ".parquet")
}
return strings.HasSuffix(name, ".arrow")
}
func (e *executor) SaveTable(name string, table arrow.Table, mem memory.Allocator) error {
if e.typeIsParquet() {
return writeTableParquet(table, name)
}
return writeTableArrow(table, name, mem)
}
func (e *executor) TableExtension() string {
if e.typeIsParquet() {
return ".parquet"
}
return ".arrow"
}
func readTableArrow(filename string, mem memory.Allocator) (arrow.Table, error) {
r, err := os.Open(filename + ".arrow")
if err != nil {
return nil, err
}
rr, err := ipc.NewFileReader(r, ipc.WithAllocator(mem))
if err != nil {
return nil, err
}
defer rr.Close()
records := make([]arrow.Record, rr.NumRecords())
i := 0
for {
rec, err := rr.Read()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
records[i] = rec
i++
}
records = records[:i]
table := array.NewTableFromRecords(rr.Schema(), records)
return table, nil
}
func readTableParquetCtx(ctx context.Context, filename string, mem memory.Allocator) (arrow.Table, error) {
r, err := os.Open(filename + ".parquet")
if err != nil {
return nil, err
}
defer r.Close()
pf, err := file.NewParquetReader(r)
if err != nil {
return nil, err
}
reader, err := pqarrow.NewFileReader(pf, pqarrow.ArrowReadProperties{}, mem)
if err != nil {
return nil, err
}
return reader.ReadTable(ctx)
}
func writeTableParquet(table arrow.Table, filename string) error {
f, err := os.Create(filename + ".parquet")
if err != nil {
return err
}
defer f.Close()
props := parquet.NewWriterProperties(parquet.WithDictionaryDefault(false))
arrProps := pqarrow.DefaultWriterProps()
chunkSize := 10 * 1024 * 1024
err = pqarrow.WriteTable(table, f, int64(chunkSize), props, arrProps)
if err != nil {
return err
}
f.Sync()
return nil
}
func writeTableArrow(table arrow.Table, filename string, mem memory.Allocator) error {
f, err := os.Create(filename + ".arrow")
if err != nil {
return err
}
defer f.Close()
writer, err := ipc.NewFileWriter(f, ipc.WithAllocator(mem), ipc.WithSchema(table.Schema()))
if err != nil {
panic(err)
}
chunkSize := int64(0)
tr := array.NewTableReader(table, chunkSize)
defer tr.Release()
n := 0
for tr.Next() {
arec := tr.Record()
err = writer.Write(arec)
if err != nil {
panic(err)
}
n++
}
err = writer.Close()
if err != nil {
panic(err)
}
f.Sync()
return nil
}

53
arrow_test.go Normal file
View file

@ -0,0 +1,53 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"context"
"encoding/hex"
"math/rand"
"os"
"path/filepath"
"testing"
"github.com/apache/arrow/go/v10/arrow"
"github.com/apache/arrow/go/v10/arrow/array"
"github.com/apache/arrow/go/v10/arrow/memory"
)
func TempFileName(prefix string) string {
randBytes := make([]byte, 16)
rand.Read(randBytes)
return filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes))
}
func Test_TableParquet(t *testing.T) {
// create a arrow table
schema := arrow.NewSchema(
[]arrow.Field{
{Name: "num", Type: arrow.PrimitiveTypes.Float64},
},
nil, // no metadata
)
mem := memory.NewGoAllocator()
b := array.NewRecordBuilder(mem, schema)
defer b.Release()
b.Field(0).(*array.Float64Builder).AppendValues([]float64{1.0, 1.5, 2.0}, nil)
table := array.NewTableFromRecords(schema, []arrow.Record{b.NewRecord()})
defer table.Release()
fileName := TempFileName("pq-")
// save it as a parquet file
err := writeTableParquet(table, fileName)
if err != nil {
t.Fatal(err)
}
defer os.Remove(fileName)
// read it back in and compare the result
got, err := readTableParquetCtx(context.Background(), fileName, mem)
if err != nil {
t.Fatalf("readTableParquetCtx() error = %v", err)
}
if got.NumCols() != table.NumCols() {
t.Errorf("got:%v expected:%v", got.NumCols(), table.NumCols())
}
}

554
attr.go
View file

@ -1,554 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pilosa
import (
"bytes"
"crypto/sha1"
"encoding/binary"
"fmt"
"sort"
"sync"
"time"
"github.com/boltdb/bolt"
"github.com/gogo/protobuf/proto"
"github.com/pilosa/pilosa/internal"
)
// AttrBlockSize is the size of attribute blocks for anti-entropy.
const AttrBlockSize = 100
// Attribute data type enum.
const (
AttrTypeString = 1
AttrTypeInt = 2
AttrTypeBool = 3
AttrTypeFloat = 4
)
// AttrCache represents a cache for attributes.
type AttrCache struct {
mu sync.RWMutex
attrs map[uint64]map[string]interface{}
}
// Get returns the cached attributes for a given id.
func (c *AttrCache) Get(id uint64) map[string]interface{} {
c.mu.RLock()
defer c.mu.RUnlock()
attrs := c.attrs[id]
if attrs == nil {
return nil
}
// Make a copy for safety
ret := make(map[string]interface{})
for k, v := range attrs {
ret[k] = v
}
return ret
}
// Set updates the cached attributes for a given id.
func (c *AttrCache) Set(id uint64, attrs map[string]interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.attrs[id] = attrs
}
// AttrStore represents a storage layer for attributes.
type AttrStore struct {
mu sync.RWMutex
path string
db *bolt.DB
attrCache *AttrCache
}
// NewAttrCache returns a new instance of AttrCache.
func NewAttrCache() *AttrCache {
return &AttrCache{
attrs: make(map[uint64]map[string]interface{}),
}
}
// NewAttrStore returns a new instance of AttrStore.
func NewAttrStore(path string) *AttrStore {
return &AttrStore{
path: path,
attrCache: NewAttrCache(),
}
}
// Path returns path to the store's data file.
func (s *AttrStore) Path() string { return s.path }
// Open opens and initializes the store.
func (s *AttrStore) Open() error {
// Open storage.
db, err := bolt.Open(s.path, 0666, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
return err
}
s.db = db
// Initialize database.
if err := s.db.Update(func(tx *bolt.Tx) error {
if _, err := tx.CreateBucketIfNotExists([]byte("attrs")); err != nil {
return err
}
return nil
}); err != nil {
return err
}
return nil
}
// Close closes the store.
func (s *AttrStore) Close() error {
if s.db != nil {
s.db.Close()
}
return nil
}
// Attrs returns a set of attributes by ID.
func (s *AttrStore) Attrs(id uint64) (m map[string]interface{}, err error) {
s.mu.RLock()
defer s.mu.RUnlock()
// Check cache for map.
if m = s.attrCache.Get(id); m != nil {
return m, nil
}
// Find attributes from storage.
if err = s.db.View(func(tx *bolt.Tx) error {
m, err = txAttrs(tx, id)
if err != nil {
return err
}
return nil
}); err != nil {
return nil, err
}
// Add to cache.
s.attrCache.Set(id, m)
return
}
// SetAttrs sets attribute values for a given ID.
func (s *AttrStore) SetAttrs(id uint64, m map[string]interface{}) error {
// Ignore empty maps.
if len(m) == 0 {
return nil
}
// Check if the attributes already exist under a read-only lock.
if attr, err := s.Attrs(id); err != nil {
return err
} else if attr != nil && mapContains(attr, m) {
return nil
}
// Obtain write lock.
s.mu.Lock()
defer s.mu.Unlock()
var attr map[string]interface{}
if err := s.db.Update(func(tx *bolt.Tx) error {
tmp, err := txUpdateAttrs(tx, id, m)
if err != nil {
return err
}
attr = tmp
return nil
}); err != nil {
return err
}
// Swap attributes map in cache.
s.attrCache.Set(id, attr)
return nil
}
// SetBulkAttrs sets attribute values for a set of ids.
func (s *AttrStore) SetBulkAttrs(m map[uint64]map[string]interface{}) error {
s.mu.Lock()
defer s.mu.Unlock()
attrs := make(map[uint64]map[string]interface{})
if err := s.db.Update(func(tx *bolt.Tx) error {
// Collect and sort keys.
ids := make([]uint64, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(uint64Slice(ids))
// Update attributes for each id.
for _, id := range ids {
attr, err := txUpdateAttrs(tx, id, m[id])
if err != nil {
return err
}
attrs[id] = attr
}
return nil
}); err != nil {
return err
}
// Swap attributes map in cache.
for id, attr := range attrs {
s.attrCache.Set(id, attr)
}
return nil
}
// Blocks returns a list of all blocks in the store.
func (s *AttrStore) Blocks() ([]AttrBlock, error) {
tx, err := s.db.Begin(false)
if err != nil {
return nil, err
}
defer tx.Rollback()
// Wrap cursor to segment by block.
cur := newBlockCursor(tx.Bucket([]byte("attrs")).Cursor(), AttrBlockSize)
// Iterate over each block.
var blocks []AttrBlock
for cur.nextBlock() {
block := AttrBlock{ID: cur.blockID()}
// Compute checksum of every key/value in block.
h := sha1.New()
for k, v := cur.next(); k != nil; k, v = cur.next() {
h.Write(k)
h.Write(v)
}
block.Checksum = h.Sum(nil)
// Append block.
blocks = append(blocks, block)
}
return blocks, nil
}
// BlockData returns all data for a single block.
func (s *AttrStore) BlockData(i uint64) (map[uint64]map[string]interface{}, error) {
m := make(map[uint64]map[string]interface{})
// Start read-only transaction.
tx, err := s.db.Begin(false)
if err != nil {
return nil, err
}
defer tx.Rollback()
// Move to the start of the block.
min := u64tob(uint64(i) * AttrBlockSize)
max := u64tob(uint64(i+1) * AttrBlockSize)
cur := tx.Bucket([]byte("attrs")).Cursor()
for k, v := cur.Seek(min); k != nil; k, v = cur.Next() {
// Exit if we're past the end of the block.
if bytes.Compare(k, max) != -1 {
break
}
// Decode attribute map and associate with id.
var pb internal.AttrMap
if err := proto.Unmarshal(v, &pb); err != nil {
return nil, err
}
m[btou64(k)] = decodeAttrs(pb.GetAttrs())
}
return m, nil
}
// txAttrs returns a map of attributes for an id.
func txAttrs(tx *bolt.Tx, id uint64) (map[string]interface{}, error) {
v := tx.Bucket([]byte("attrs")).Get(u64tob(id))
if v == nil {
return emptyMap, nil
}
var pb internal.AttrMap
if err := proto.Unmarshal(v, &pb); err != nil {
return nil, err
}
return decodeAttrs(pb.GetAttrs()), nil
}
// txUpdateAttrs updates the attributes for an id.
// Returns the new combined set of attributes for the id.
func txUpdateAttrs(tx *bolt.Tx, id uint64, m map[string]interface{}) (map[string]interface{}, error) {
attr, err := txAttrs(tx, id)
if err != nil {
return nil, err
}
// Create a new map if it is empty so we don't update emptyMap.
if len(attr) == 0 {
attr = make(map[string]interface{}, len(m))
}
// Merge attributes with original values.
// Nil values should delete keys.
for k, v := range m {
if v == nil {
delete(attr, k)
continue
}
switch v := v.(type) {
case int:
attr[k] = int64(v)
case uint:
attr[k] = int64(v)
case uint64:
attr[k] = int64(v)
case string, int64, bool, float64:
attr[k] = v
default:
return nil, fmt.Errorf("invalid attr type: %T", v)
}
}
// Marshal and save new values.
buf, err := proto.Marshal(&internal.AttrMap{Attrs: encodeAttrs(attr)})
if err != nil {
return nil, err
}
if err := tx.Bucket([]byte("attrs")).Put(u64tob(id), buf); err != nil {
return nil, err
}
return attr, nil
}
func encodeAttrs(m map[string]interface{}) []*internal.Attr {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
a := make([]*internal.Attr, len(keys))
for i := range keys {
a[i] = encodeAttr(keys[i], m[keys[i]])
}
return a
}
func decodeAttrs(pb []*internal.Attr) map[string]interface{} {
m := make(map[string]interface{}, len(pb))
for i := range pb {
key, value := decodeAttr(pb[i])
m[key] = value
}
return m
}
// encodeAttr converts a key/value pair into an Attr internal representation.
func encodeAttr(key string, value interface{}) *internal.Attr {
pb := &internal.Attr{Key: key}
switch value := value.(type) {
case string:
pb.Type = AttrTypeString
pb.StringValue = value
case float64:
pb.Type = AttrTypeFloat
pb.FloatValue = value
case uint64:
pb.Type = AttrTypeInt
pb.IntValue = int64(value)
case int64:
pb.Type = AttrTypeInt
pb.IntValue = value
case bool:
pb.Type = AttrTypeBool
pb.BoolValue = value
}
return pb
}
// decodeAttr converts from an Attr internal representation to a key/value pair.
func decodeAttr(attr *internal.Attr) (key string, value interface{}) {
switch attr.Type {
case AttrTypeString:
return attr.Key, attr.StringValue
case AttrTypeInt:
return attr.Key, attr.IntValue
case AttrTypeBool:
return attr.Key, attr.BoolValue
case AttrTypeFloat:
return attr.Key, attr.FloatValue
default:
return attr.Key, nil
}
}
// cloneAttrs returns a shallow clone of m.
func cloneAttrs(m map[string]interface{}) map[string]interface{} {
other := make(map[string]interface{}, len(m))
for k, v := range m {
other[k] = v
}
return other
}
// u64tob encodes v to big endian encoding.
func u64tob(v uint64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, v)
return b
}
// btou64 decodes b from big endian encoding.
func btou64(b []byte) uint64 { return binary.BigEndian.Uint64(b) }
// emptyMap is a reusable map that contains no keys.
var emptyMap = make(map[string]interface{})
// AttrBlock represents a checksummed block of the attribute store.
type AttrBlock struct {
ID uint64 `json:"id"`
Checksum []byte `json:"checksum"`
}
// AttrBlocks represents a list of blocks.
type AttrBlocks []AttrBlock
// Diff returns a list of block ids that are different or are new in other.
// Block lists must be in sorted order.
func (a AttrBlocks) Diff(other []AttrBlock) []uint64 {
var ids []uint64
for {
// Read next block from each list.
var blk0, blk1 *AttrBlock
if len(a) > 0 {
blk0 = &a[0]
}
if len(other) > 0 {
blk1 = &other[0]
}
// Exit if "a" contains no more blocks.
if blk0 == nil {
return ids
}
// Add block ID if it's different or if it's only in "a".
if blk1 == nil || blk0.ID < blk1.ID {
ids = append(ids, blk0.ID)
a = a[1:]
} else if blk1.ID < blk0.ID {
other = other[1:]
} else {
if !bytes.Equal(blk0.Checksum, blk1.Checksum) {
ids = append(ids, blk0.ID)
}
a, other = a[1:], other[1:]
}
}
}
// blockCursor represents a cursor for iterating over blocks of a bolt bucket.
type blockCursor struct {
cur *bolt.Cursor
base uint64
n uint64
buf struct {
key []byte
value []byte
filled bool
}
}
// newBlockCursor returns a new block cursor that wraps cur using n sized blocks.
func newBlockCursor(c *bolt.Cursor, n int) blockCursor {
cur := blockCursor{
cur: c,
n: uint64(n),
}
cur.buf.key, cur.buf.value = c.First()
cur.buf.filled = true
return cur
}
// blockID returns the current block ID. Only valid after call to nextBlock().
func (cur *blockCursor) blockID() uint64 { return cur.base }
// nextBlock moves the cursor to the next block.
// Returns true if another block exists, otherwise returns false.
func (cur *blockCursor) nextBlock() bool {
if cur.buf.key == nil {
return false
}
cur.base = binary.BigEndian.Uint64(cur.buf.key) / cur.n
return true
}
// next returns the next key/value within the block.
// Returns nils at the end of the block.
func (cur *blockCursor) next() (key, value []byte) {
// Use buffered value, if set.
if cur.buf.filled {
key, value = cur.buf.key, cur.buf.value
cur.buf.filled = false
return key, value
}
// Read next key.
key, value = cur.cur.Next()
// Fill buffer for EOF.
if key == nil {
cur.buf.key, cur.buf.value, cur.buf.filled = key, value, false
return nil, nil
}
// Parse key and buffer if outside of block.
id := binary.BigEndian.Uint64(key)
if id/cur.n > cur.base {
cur.buf.key, cur.buf.value, cur.buf.filled = key, value, true
return nil, nil
}
return key, value
}
// mapContains returns true if all keys & values of subset are in m.
func mapContains(m, subset map[string]interface{}) bool {
for k, v := range subset {
value, ok := m[k]
if !ok || value != v {
return false
}
}
return true
}

View file

@ -1,125 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pilosa_test
import (
"reflect"
"testing"
"github.com/pilosa/pilosa/test"
)
// Ensure database can set and retrieve column attributes.
func TestAttrStore_Attrs(t *testing.T) {
s := test.MustOpenAttrStore()
defer s.Close()
// Set attributes.
if err := s.SetAttrs(1, map[string]interface{}{"A": 100, "C": -27}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(2, map[string]interface{}{"A": uint64(200)}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(1, map[string]interface{}{"B": "VALUE"}); err != nil {
t.Fatal(err)
}
// Retrieve attributes for column #1.
if m, err := s.Attrs(1); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(m, map[string]interface{}{"A": int64(100), "B": "VALUE", "C": int64(-27)}) {
t.Fatalf("unexpected attrs(1): %#v", m)
}
// Retrieve attributes for column #2.
if m, err := s.Attrs(2); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(m, map[string]interface{}{"A": int64(200)}) {
t.Fatalf("unexpected attrs(2): %#v", m)
}
}
// Ensure database returns a non-nil empty map if unset.
func TestAttrStore_Attrs_Empty(t *testing.T) {
s := test.MustOpenAttrStore()
defer s.Close()
if m, err := s.Attrs(100); err != nil {
t.Fatal(err)
} else if m == nil || len(m) > 0 {
t.Fatalf("unexpected attrs: %#v", m)
}
}
// Ensure database can unset attributes if explicitly set to nil.
func TestAttrStore_Attrs_Unset(t *testing.T) {
s := test.MustOpenAttrStore()
defer s.Close()
// Set attributes.
if err := s.SetAttrs(1, map[string]interface{}{"A": "X", "B": "Y"}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(1, map[string]interface{}{"B": nil}); err != nil {
t.Fatal(err)
}
// Verify attributes.
if m, err := s.Attrs(1); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(m, map[string]interface{}{"A": "X"}) {
t.Fatalf("unexpected attrs: %#v", m)
}
}
// Ensure attribute block checksums can be returned.
func TestAttrStore_Blocks(t *testing.T) {
s := test.MustOpenAttrStore()
defer s.Close()
// Set attributes.
if err := s.SetAttrs(1, map[string]interface{}{"A": uint64(100)}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(2, map[string]interface{}{"A": uint64(200)}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(100, map[string]interface{}{"B": "VALUE"}); err != nil {
t.Fatal(err)
} else if err := s.SetAttrs(350, map[string]interface{}{"C": "FOO"}); err != nil {
t.Fatal(err)
}
// Retrieve blocks.
blks0, err := s.Blocks()
if err != nil {
t.Fatal(err)
} else if len(blks0) != 3 || blks0[0].ID != 0 || blks0[1].ID != 1 || blks0[2].ID != 3 {
t.Fatalf("unexpected blocks: %#v", blks0)
}
// Change second block.
if err := s.SetAttrs(100, map[string]interface{}{"X": 12}); err != nil {
t.Fatal(err)
}
// Ensure second block changed.
blks1, err := s.Blocks()
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(blks0[0], blks1[0]) {
t.Fatalf("block 0 mismatch: %#v != %#v", blks0[0], blks1[0])
} else if reflect.DeepEqual(blks0[1], blks1[1]) {
t.Fatalf("block 1 match: %#v ", blks0[0])
} else if !reflect.DeepEqual(blks0[2], blks1[2]) {
t.Fatalf("block 2 mismatch: %#v != %#v", blks0[2], blks1[2])
}
}

13
audit.go Normal file
View file

@ -0,0 +1,13 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"github.com/featurebasedb/featurebase/v3/testhook"
)
var NewAuditor func() testhook.Auditor = NewNopAuditor
func NewNopAuditor() testhook.Auditor {
return testhook.NewNopAuditor()
}

40
audit_internal_test.go Normal file
View file

@ -0,0 +1,40 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"fmt"
"reflect"
"github.com/featurebasedb/featurebase/v3/testhook"
)
// These audit hooks are desireable during testing, but not in
// production.
type auditorViewHooks struct{}
type auditorFragmentHooks struct{}
// static type checks
var _ testhook.RegistryHookLive = &auditorViewHooks{}
var _ testhook.RegistryHookLive = &auditorFragmentHooks{}
func (*auditorViewHooks) Live(o interface{}, entry *testhook.RegistryEntry) error {
if entry != nil && entry.OpenCount != 0 {
return fmt.Errorf("view %s still open", o.(*view).name)
}
return nil
}
func (*auditorFragmentHooks) Live(o interface{}, entry *testhook.RegistryEntry) error {
if entry != nil && entry.OpenCount != 0 {
return fmt.Errorf("fragment %s still open", o.(*fragment).path())
}
return nil
}
func GetInternalTestHooks() testhook.RegistryHooks {
return map[reflect.Type]testhook.RegistryHook{
reflect.TypeOf((*view)(nil)): &auditorViewHooks{},
reflect.TypeOf((*fragment)(nil)): &auditorFragmentHooks{},
}
}

95
audit_test.go Normal file
View file

@ -0,0 +1,95 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa_test
import (
"fmt"
"os"
"reflect"
"github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/testhook"
)
// AuditLeaksOn is a global switch to turn on resource
// leak checking at the end of a test run.
var AuditLeaksOn = true
// for tests, we use a single shared auditor used by all of the holders.
var globalTestAuditor = testhook.NewVerifyCloseAuditor(testHooks)
// These audit hooks are desireable during testing, but not in
// production.
type auditorIndexHooks struct{}
type auditorFieldHooks struct{}
type auditorHolderHooks struct{}
// static type checking
var _ testhook.RegistryHookLive = &auditorIndexHooks{}
var _ testhook.RegistryHookLive = &auditorFieldHooks{}
var _ testhook.RegistryHookPostDestroy = &auditorHolderHooks{}
var _ testhook.RegistryHookLive = &auditorHolderHooks{}
var testHooks = map[reflect.Type]testhook.RegistryHook{
reflect.TypeOf((*pilosa.Index)(nil)): &auditorIndexHooks{},
reflect.TypeOf((*pilosa.Field)(nil)): &auditorFieldHooks{},
reflect.TypeOf((*pilosa.Holder)(nil)): &auditorHolderHooks{},
}
func init() {
if !AuditLeaksOn {
return
}
for k, v := range pilosa.GetInternalTestHooks() {
testHooks[k] = v
}
testhook.RegisterPreTestHook(func() error {
pilosa.NewAuditor = NewTestAuditor
return nil
})
testhook.RegisterPostTestHook(func() error {
err, errs := globalTestAuditor.FinalCheck()
if err != nil {
for i, e := range errs {
fmt.Fprintf(os.Stderr, "[%d]: %v\n", i, e)
}
}
return err
})
}
func NewTestAuditor() testhook.Auditor {
return globalTestAuditor
}
func (*auditorIndexHooks) Live(o interface{}, entry *testhook.RegistryEntry) error {
if entry != nil && entry.OpenCount != 0 {
return fmt.Errorf("index %s still open", o.(*pilosa.Index).Name())
}
return nil
}
func (*auditorFieldHooks) Live(o interface{}, entry *testhook.RegistryEntry) error {
if entry != nil && entry.OpenCount != 0 {
return fmt.Errorf("field %s still open", o.(*pilosa.Field).Name())
}
return nil
}
func (*auditorHolderHooks) WasDestroyed(o interface{}, kv testhook.KV, ent *testhook.RegistryEntry, err error) error {
path := o.(*pilosa.Holder).Path()
if path == "" {
fmt.Fprintf(os.Stderr, "OOPS: trying to destroy a holder with no path! created: %s\n",
ent.Stack)
} else {
os.RemoveAll(o.(*pilosa.Holder).Path())
}
return err
}
func (*auditorHolderHooks) Live(o interface{}, entry *testhook.RegistryEntry) error {
if entry != nil && entry.OpenCount != 0 {
return fmt.Errorf("holder %s still open", o.(*pilosa.Holder).Path())
}
return nil
}

445
authn/authenticate.go Normal file
View file

@ -0,0 +1,445 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
// Package authn handles authentication
package authn
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/golang-jwt/jwt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/featurebasedb/featurebase/v3/logger"
"github.com/pkg/errors"
"golang.org/x/oauth2"
)
// AuthContextKey is a unique type to prevent collisions when using context.WithValue()
type AuthContextKey string
const (
// AccessCookieName is the name of the cookie that holds the access token.
AccessCookieName = "molecula-chip"
// RefreshCookieName is the name of the cookie that holds the refresh token.
RefreshCookieName = "refresh-molecula-chip"
// RefreshHeaderName is the name of the header that holds the refresh token.
RefreshHeaderName = "X-Molecula-Refresh-Token"
// ContextValueAccessToken is the key used to set AccessTokens in a ctx.
ContextValueAccessToken = AuthContextKey("Access")
// ContextValueRefreshToken is the key used to set RefreshTokens in a ctx.
ContextValueRefreshToken = AuthContextKey("Refresh")
)
// cachedGroups is used to hold groups and when they were last cached
type cachedGroups struct {
cacheTime time.Time
groups []Group
}
// UserInfo holds the information about the user from the token
type UserInfo struct {
UserID string `json:"userid"`
UserName string `json:"username"`
Groups []Group `json:"groups"`
Expiry time.Time `json:"expiry"`
Token string `json:"token"`
RefreshToken string `json:"refreshtoken"`
}
// Group holds group information for an authenticated user
type Group struct {
GroupID string `json:"id"`
GroupName string `json:"displayName"`
}
// Groups holds a slice of Group for marshalling from JSON
type Groups struct {
NextLink string `json:"@odata.nextLink"`
Groups []Group `json:"value"`
}
// Auth holds state, configuration, and utilities needed for authentication.
type Auth struct {
logger logger.Logger
accessCookieName string
refreshCookieName string
secretKey []byte
groupEndpoint string
logoutEndpoint string
fbURL string // fbURL is the domain featurebase is hosted on, used for post logout redirection
oAuthConfig *oauth2.Config
cacheTTL time.Duration // cacheTTL is used to determine if a cached item should be refreshed or not
groupsCache map[string]cachedGroups // groupsCache is a map of accessToken -> group memberships
lastCacheClean time.Time // last cache clean is the time that the cache was last cleaned
allowedNetworks []net.IPNet // list of allowed networks for ingest
}
// NewAuth instantiates and returns a new Auth struct
func NewAuth(logger logger.Logger, url string, scopes []string, authURL, tokenURL, groupEndpoint, logout, clientID, clientSecret, secretKey string, configuredIPs []string) (auth *Auth, err error) {
auth = &Auth{
logger: logger,
accessCookieName: AccessCookieName,
refreshCookieName: RefreshCookieName,
groupEndpoint: groupEndpoint,
logoutEndpoint: logout,
fbURL: url,
oAuthConfig: &oauth2.Config{
RedirectURL: fmt.Sprintf("%s/redirect", url),
ClientID: clientID,
ClientSecret: clientSecret,
Scopes: scopes,
Endpoint: oauth2.Endpoint{
AuthURL: authURL,
TokenURL: tokenURL,
},
},
groupsCache: map[string]cachedGroups{},
cacheTTL: 10 * time.Minute,
lastCacheClean: time.Now(),
}
if auth.secretKey, err = decodeHex(secretKey); err != nil {
return nil, errors.Wrap(err, "decoding secret key")
}
// convert IPs and add them to allowed networks
err = auth.convertIP(configuredIPs)
if err != nil {
return nil, err
}
return auth, nil
}
// CleanOAuthConfig returns a's oauthConfig without the client secret
func (a Auth) CleanOAuthConfig() oauth2.Config {
b := *a.oAuthConfig
b.ClientSecret = ""
return b
}
// SecretKey is a convenient function to get the SecretKey from an Auth struct
func (a Auth) SecretKey() []byte {
return a.secretKey
}
// refreshToken refreshes a given access/refresh token pair
func (a *Auth) refreshToken(access, refresh string) (string, string, error) {
resp, err := http.PostForm(a.oAuthConfig.Endpoint.TokenURL,
url.Values{
"grant_type": {"refresh_token"},
"refresh_token": {refresh},
"client_id": {a.oAuthConfig.ClientID},
"client_secret": {a.oAuthConfig.ClientSecret},
},
)
if err != nil {
return "", "", errors.Wrap(err, "refreshing token")
}
if resp.StatusCode != http.StatusOK {
return "", "", fmt.Errorf("refreshing token: %s", resp.Status)
}
defer resp.Body.Close()
var t oauth2.Token
if err := json.NewDecoder(resp.Body).Decode(&t); err != nil {
return "", "", errors.Wrap(err, "decoding refreshed token")
}
// remove the old groups from the groups cache
delete(a.groupsCache, access)
return t.AccessToken, t.RefreshToken, nil
}
// Authenticate takes in a auth token `access` and returns UserInfo from that token
// it is caller's responsibility to inform the user that the access token has been refreshed
func (a *Auth) Authenticate(access, refresh string) (*UserInfo, error) {
// clean up the cache every 30 minutes or so
if time.Since(a.lastCacheClean) >= 30*time.Minute {
a.cleanCache()
}
if len(access) == 0 {
return nil, fmt.Errorf("auth token is empty")
}
// NOTE: we are using ParseUnverified here because the IDP validates the
// token's signature when we get the user's groups, we just need to make
// sure it's not expired and is well-formed
token, _, err := new(jwt.Parser).ParseUnverified(access, &jwt.MapClaims{})
// well-formed-ness check
if token == nil || token.Claims == nil || err != nil {
return nil, fmt.Errorf("parsing auth token: %v", err)
}
claims := *token.Claims.(*jwt.MapClaims)
// expiry check
if exp, ok := claims["exp"]; ok {
var expiry int64
switch v := exp.(type) {
case string:
expiry, err = strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, fmt.Errorf("parsing exp string: %v", err)
}
case float64:
expiry = int64(v)
case int64:
expiry = v
}
if expiry < time.Now().UTC().Unix() {
access, refresh, err = a.refreshToken(access, refresh)
if err != nil {
return nil, fmt.Errorf("token is expired: %w", err)
}
}
}
userInfo := UserInfo{
Token: access,
RefreshToken: refresh,
Groups: []Group{},
}
if uid, ok := claims["oid"].(string); ok {
userInfo.UserID = uid
}
if name, ok := claims["name"].(string); ok {
userInfo.UserName = name
}
if userInfo.Groups, err = a.getGroups(access); err != nil {
return nil, errors.Wrap(err, "getting groups")
}
return &userInfo, nil
}
// cleanCache removes old items from our cache
func (a *Auth) cleanCache() {
for access, tkn := range a.groupsCache {
// if it's been more than 24 hours since the groups were cached
if time.Since(tkn.cacheTime) >= 24*time.Hour {
// remove it from our cache
delete(a.groupsCache, access)
}
}
a.lastCacheClean = time.Now()
}
// Login redirects a user to login to their configured oAuth authorize endpoint
func (a *Auth) Login(w http.ResponseWriter, r *http.Request) {
authURL := a.oAuthConfig.AuthCodeURL(a.oAuthConfig.Endpoint.AuthURL)
http.Redirect(w, r, authURL, http.StatusTemporaryRedirect)
}
// Logout clears out the user's cookie, removes the token from our cache, and
// redirects user to IdP's logout endpoint
func (a *Auth) Logout(w http.ResponseWriter, r *http.Request) {
// remove the access token from a.groupsCache
if access, err := r.Cookie(a.accessCookieName); err == nil {
delete(a.groupsCache, access.Value)
}
// clear cookie
http.SetCookie(w, &http.Cookie{
Name: a.accessCookieName,
Value: "",
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: time.Unix(0, 0),
})
http.SetCookie(w, &http.Cookie{
Name: a.refreshCookieName,
Value: "",
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: time.Unix(0, 0),
})
http.Redirect(w, r, fmt.Sprintf("%s?post_logout_redirect_uri=%s/", a.logoutEndpoint, a.fbURL), http.StatusTemporaryRedirect)
}
// Redirect handles the oAuth /redirect endpoint. It gets an access token and
// returns it to the user in the form of a cookie
func (a *Auth) Redirect(w http.ResponseWriter, r *http.Request) {
token, err := a.oAuthConfig.Exchange(r.Context(), r.FormValue("code"), oauth2.AccessTypeOffline)
if err != nil {
a.logger.Warnf("getting token from IdP: %+v", err)
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
a.SetCookie(w, token.AccessToken, token.RefreshToken, token.Expiry)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}
// getGroups gets the group membership for a given token from configured IdP
func (a *Auth) getGroups(token string) ([]Group, error) {
var groups Groups
gc, ok := a.groupsCache[token]
if ok && (time.Since(gc.cacheTime) < a.cacheTTL) && len(gc.groups) > 0 {
return gc.groups, nil
}
nextLink := a.groupEndpoint
for nextLink != "" {
req, err := http.NewRequest("GET", nextLink, nil)
if err != nil {
return nil, errors.Wrap(err, "creating new request to group endpoint")
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
response, err := http.DefaultClient.Do(req)
if err != nil {
return nil, errors.Wrap(err, "getting group membership info")
}
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("getting group membership info: %s", response.Status)
}
var g Groups
if err = json.NewDecoder(response.Body).Decode(&g); err != nil {
return groups.Groups, errors.Wrap(err, "failed unmarshalling group membership response")
}
response.Body.Close()
groups.Groups = append(groups.Groups, g.Groups...)
nextLink = g.NextLink
}
if len(groups.Groups) == 0 {
return nil, fmt.Errorf("no groups found")
}
a.groupsCache[token] = cachedGroups{
cacheTime: time.Now(),
groups: groups.Groups,
}
return groups.Groups, nil
}
func (a *Auth) SetCookie(w http.ResponseWriter, access, refresh string, expiry time.Time) error {
http.SetCookie(w, &http.Cookie{
Name: a.refreshCookieName,
Value: refresh,
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: expiry,
})
http.SetCookie(w, &http.Cookie{
Name: a.accessCookieName,
Value: access,
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: expiry,
})
return nil
}
func (a *Auth) SetGRPCMetadata(ctx context.Context, md metadata.MD, access, refresh string) (context.Context, error) {
mCookies := map[string]string{}
if c, ok := md["cookie"]; ok {
for _, cookie := range c {
name, val := parseCookie(cookie)
mCookies[name] = val
}
}
mCookies[a.accessCookieName] = access
mCookies[a.refreshCookieName] = refresh
cookies := []string{}
for name, val := range mCookies {
cookies = append(cookies, name+"="+val)
}
md["cookie"] = cookies
return metadata.NewIncomingContext(ctx, md), grpc.SetHeader(ctx, md)
}
func decodeHex(hexstr string) ([]byte, error) {
data, err := hex.DecodeString(hexstr)
if err != nil {
return nil, errors.Wrap(err, "decoding hex string to byte slice")
}
if len(data) != 32 {
return nil, fmt.Errorf("invalid key length")
}
return data, nil
}
func (a *Auth) convertIP(configuredIPs []string) error {
sz := len(configuredIPs)
nets := make([]net.IPNet, sz)
for i, ip := range configuredIPs {
// skip empty strings
if ip == "" {
sz--
continue
}
// for IPs passed without a subnet, append /32 to only allow 1 IP
// this step is needed because ParseCIDR method assumes a CIDR address
if !strings.Contains(ip, "/") {
ip = ip + "/32"
}
_, subnet, err := net.ParseCIDR(ip)
if err != nil {
return errors.Wrapf(err, "parsing CIDR for %v", ip)
}
nets[i] = *subnet
}
a.allowedNetworks = nets[:sz]
return nil
}
// if IP is in allowed networks, then return true to grant admin permissions
func (a *Auth) CheckAllowedNetworks(clientIP string) bool {
clientIP = strings.Split(clientIP, ":")[0]
convertedIP := net.ParseIP(clientIP)
for _, network := range a.allowedNetworks {
if network.Contains(convertedIP) {
return true
}
}
return false
}
func parseCookie(cookie string) (name, data string) {
vals := strings.Split(cookie, "=")
if len(vals) == 0 {
vals = []string{"", ""}
} else if len(vals) < 2 {
vals = append(vals, "")
}
return vals[0], vals[1]
}

View file

@ -0,0 +1,760 @@
package authn
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net"
"net/http"
"net/http/httptest"
"os"
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/featurebasedb/featurebase/v3/logger"
"github.com/golang-jwt/jwt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
func NewTestAuth(t *testing.T) *Auth {
t.Helper()
var (
ClientID = "e9088663-eb08-41d7-8f65-efb5f54bbb71"
ClientSecret = "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"
AuthorizeURL = "https://login.microsoftonline.com/4a137d66-d161-4ae4-b1e6-07e9920874b8/oauth2/v2.0/authorize"
TokenURL = "https://login.microsoftonline.com/4a137d66-d161-4ae4-b1e6-07e9920874b8/oauth2/v2.0/token"
GroupEndpointURL = "https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.group?$count=true"
LogoutURL = "https://login.microsoftonline.com/common/oauth2/v2.0/logout"
Scopes = []string{"https://graph.microsoft.com/.default", "offline_access"}
Key = "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"
configuredIPs = []string{}
)
a, err := NewAuth(
logger.NewStandardLogger(os.Stdout),
"http://localhost:10101/",
Scopes,
AuthorizeURL,
TokenURL,
GroupEndpointURL,
LogoutURL,
ClientID,
ClientSecret,
Key,
configuredIPs,
)
if err != nil {
t.Fatalf("building auth object%s", err)
}
return a
}
func TestSetGRPCMetadata(t *testing.T) {
a := NewTestAuth(t)
for name, md := range map[string]metadata.MD{
"empty": {},
"something": {"cookie": []string{a.accessCookieName + "=something"}},
"somethingElse": {"cookie": []string{
a.accessCookieName + "=something",
a.refreshCookieName + "=something",
}},
"otherCookies": {"cookie": []string{a.accessCookieName + "=something", "blah=blah"}},
} {
t.Run(name, func(t *testing.T) {
ogCookies := md["cookie"]
ctx := grpc.NewContextWithServerTransportStream(
metadata.NewIncomingContext(context.TODO(),
md,
),
NewServerTransportStream(),
)
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
t.Fatalf("expected ok, got: %v", ok)
}
ctx, err := a.SetGRPCMetadata(ctx, md, "accesstoken!", "refreshtoken!")
if err != nil {
t.Fatalf("expected no errors, got: %v", err)
}
if err := grpc.SendHeader(ctx, md); err != nil {
t.Fatalf("expected no errors, got: %v", err)
}
md, ok = metadata.FromIncomingContext(ctx)
if !ok {
t.Fatalf("expected ok, got: %v", ok)
}
c, ok := md["cookie"]
if !ok {
t.Fatalf("expected ok, got: %v", ok)
}
var accessCookie, refreshCookie string
for _, cookie := range c {
if strings.HasPrefix(cookie, a.accessCookieName) {
accessCookie = cookie
} else if strings.HasPrefix(cookie, a.refreshCookieName) {
refreshCookie = cookie
}
if refreshCookie != "" && accessCookie != "" {
break
}
}
exp := a.accessCookieName + "=accesstoken!"
if accessCookie != exp {
t.Fatalf("expected '%v', got '%v'", exp, accessCookie)
}
exp = a.refreshCookieName + "=refreshtoken!"
if refreshCookie != exp {
t.Fatalf("expected '%v', got '%v'", exp, refreshCookie)
}
for _, cookie := range c {
if strings.HasPrefix(cookie, a.accessCookieName) || strings.HasPrefix(cookie, a.refreshCookieName) {
continue
}
found := false
for _, ogCookie := range ogCookies {
if cookie == ogCookie {
found = true
break
}
}
if !found {
t.Fatal("SetGRPCMetadata did not maintain the previous cookie list")
}
}
})
}
}
func TestAuth(t *testing.T) {
a := NewTestAuth(t)
t.Run("SetCookie", func(t *testing.T) {
w := httptest.NewRecorder()
err := a.SetCookie(w, "access", "refresh", time.Now().Add(time.Hour))
if err != nil {
t.Fatalf("expected no errors, got: %v", err)
}
if w.Result().Cookies()[0].Value == "" {
t.Errorf("expected something, got empty string")
}
if got, want := w.Result().Cookies()[0].Path, "/"; got != want {
t.Fatalf("path=%s, want %s", got, want)
}
})
t.Run("KeyLength", func(t *testing.T) {
_, err := NewAuth(
logger.NewStandardLogger(os.Stdout),
"http://localhost:10101/",
[]string{"https://graph.microsoft.com/.default", "offline_access"},
"https://login.microsoftonline.com/4a137d66-d161-4ae4-b1e6-07e9920874b8/oauth2/v2.0/authorize",
"https://login.microsoftonline.com/4a137d66-d161-4ae4-b1e6-07e9920874b8/oauth2/v2.0/token",
"https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.group?$count=true",
"https://login.microsoftonline.com/common/oauth2/v2.0/logout",
"e9088663-eb08-41d7-8f65-efb5f54bbb71",
"DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
"DEADBEEFD",
[]string{},
)
if err == nil || !strings.Contains(err.Error(), "decoding secret key") {
t.Fatalf("expected error decoding secret key got: %v", err)
}
})
t.Run("GetSecretKey", func(t *testing.T) {
want, _ := hex.DecodeString("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")
if got := a.SecretKey(); !bytes.Equal(got, want) {
t.Fatalf("expected %v, got %v", got, want)
}
})
}
func TestAuthenticate(t *testing.T) {
cases := []struct {
name string
uid string
uname string
exp int64
refresh bool
refreshToken string
malformed bool
empty bool
groups []Group
err error
}{
{
name: "GoodToken",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
},
{
name: "Malformed",
malformed: true,
err: fmt.Errorf("parsing auth token: token contains an invalid number of segments"),
},
{
name: "Empty",
empty: true,
err: fmt.Errorf("auth token is empty"),
},
{
name: "ExpiredTokenNoRefresh",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
exp: -17764800,
err: fmt.Errorf("token is expired: refreshing token: 400 Bad Request"),
},
{
name: "ExpiredTokenYesRefresh",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
refresh: true,
refreshToken: "refreshToken",
exp: -17764800,
},
{
name: "ExpiredTokenYesRefreshButError",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
refresh: true,
refreshToken: "blah!!",
exp: -17764800,
err: fmt.Errorf("token is expired: refreshing token: 403 Forbidden"),
},
}
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
// setup the test
a := NewTestAuth(t)
token := ""
var err error
if !test.malformed && !test.empty {
tkn := jwt.New(jwt.SigningMethodHS256)
claims := tkn.Claims.(jwt.MapClaims)
claims["oid"] = test.uid
claims["name"] = test.uname
if test.exp != 0 {
claims["exp"] = float64(test.exp)
}
token, err = tkn.SignedString(a.SecretKey())
if err != nil {
t.Fatalf("unexpected error when signing token %v", err)
}
} else if !test.empty {
token = "asdfasdfasdfasdF"
}
if len(test.groups) > 0 {
a.groupsCache[token] = cachedGroups{time.Now(), test.groups}
}
if test.refresh {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
refresh := r.Form.Get("refresh_token")
if refresh != test.refreshToken {
t.Fatalf("refresh token not passed properly, expected %v, got %v", test.refreshToken, refresh)
return
}
if refresh != "refreshToken" {
http.Error(w, "bad token", http.StatusForbidden)
}
tkn := jwt.New(jwt.SigningMethodHS256)
claims := tkn.Claims.(jwt.MapClaims)
claims["oid"] = test.uid
claims["name"] = test.uname
expiry := float64(time.Now().Add(2 * time.Hour).Unix())
claims["exp"] = expiry
fresh, err := tkn.SignedString(a.SecretKey())
if err != nil {
t.Fatalf("unexpected error when signing token %v", err)
}
a.groupsCache[fresh] = cachedGroups{time.Now(), test.groups}
fmt.Fprintf(w, `{"access_token": "`+fresh+`", "refresh_token": "blah", "token_type": "bearer", "expires": `+strconv.FormatFloat(expiry, 'f', 0, 64)+` }`)
}))
defer srv.Close()
a.oAuthConfig.Endpoint.TokenURL = srv.URL
}
// do the actual testing
uinfo, err := a.Authenticate(token, test.refreshToken)
// okay this part kind of sucks bc we need to check errors and i
// dont want to write a whole new test for things that should have
// errors just to avoid this mess. errors.Is doesn't work either
if (test.err == nil && err != nil) || (test.err != nil && err == nil) {
t.Fatalf("expected %v, but got %v", test.err, err)
} else if test.err != nil && err != nil {
if test.err.Error() != err.Error() {
t.Fatalf("expected %v, but got %v", test.err, err)
} else {
return
}
}
if !reflect.DeepEqual(uinfo.Groups, test.groups) {
t.Fatalf("expected %v, got %v", test.groups, uinfo.Groups)
}
if !reflect.DeepEqual(uinfo.UserID, test.uid) {
t.Fatalf("expected %v, got %v", test.uid, uinfo.UserID)
}
if !reflect.DeepEqual(uinfo.UserName, test.uname) {
t.Fatalf("expected %v, got %v", test.uname, uinfo.UserName)
}
})
}
}
func TestAuthenticate_CleanCache(t *testing.T) {
// this deserves its own test bc it has gross setup required
t.Run("should clean", func(t *testing.T) {
a := NewTestAuth(t)
now := time.Now()
a.groupsCache["oldy"] = cachedGroups{now.Add(-24 * time.Hour), []Group{}}
a.groupsCache["goldy"] = cachedGroups{now.Add(-4 * time.Hour), []Group{}}
a.lastCacheClean = now.Add(-45 * time.Minute)
_, _ = a.Authenticate("this doesn't matter", "this doesn't matter?")
if a.lastCacheClean.Sub(now) <= time.Nanosecond {
t.Fatalf("cache should have been cleaned")
}
if _, ok := a.groupsCache["oldy"]; ok {
t.Errorf("oldy should have been deleted")
}
if _, ok := a.groupsCache["goldy"]; !ok {
t.Errorf("goldy should not have been deleted")
}
})
t.Run("shouldn't clean", func(t *testing.T) {
a := NewTestAuth(t)
now := time.Now()
a.groupsCache["oldy"] = cachedGroups{now.Add(-24 * time.Hour), []Group{}}
a.groupsCache["goldy"] = cachedGroups{now.Add(-4 * time.Hour), []Group{}}
a.lastCacheClean = now
_, _ = a.Authenticate("this doesn't matter", "this doesn't matter?")
if a.lastCacheClean.Sub(now) >= time.Nanosecond {
t.Fatalf("cache should not have been cleaned")
}
if _, ok := a.groupsCache["oldy"]; !ok {
t.Errorf("oldy should not have been deleted")
}
if _, ok := a.groupsCache["goldy"]; !ok {
t.Errorf("goldy should not have been deleted")
}
})
}
func TestGetGroups(t *testing.T) {
a := NewTestAuth(t)
a.groupsCache = map[string]cachedGroups{
"the world is changed": {
cacheTime: time.Now(),
groups: []Group{
{
GroupID: "a han noston ned wilith",
GroupName: "I smell it in the air",
},
},
},
}
srvNext := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := json.Marshal(
Groups{
Groups: []Group{
{
GroupID: "han mathon ne chae",
GroupName: "I feel it in the earth",
},
},
},
)
if err != nil {
t.Fatalf("unexpected error marshalling groups response: %v", err)
}
fmt.Fprintf(w, "%s", body)
}))
defer srvNext.Close()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := json.Marshal(
Groups{
NextLink: srvNext.URL,
Groups: []Group{
{
GroupID: "han mathon ne nen",
GroupName: "i feel it in the water",
},
},
},
)
if err != nil {
t.Fatalf("unexpected error marshalling groups response: %v", err)
}
fmt.Fprintf(w, "%s", body)
}))
defer srv.Close()
a.groupEndpoint = srv.URL
for name, test := range map[string]struct {
token string
groups []Group
}{
"InCache": {
token: "the world is changed",
groups: []Group{
{
GroupID: "a han noston ned wilith",
GroupName: "I smell it in the air",
},
},
},
"NotInCache": {
token: "i smell it in the air",
groups: []Group{
{
GroupID: "han mathon ne nen",
GroupName: "i feel it in the water",
},
{
GroupID: "han mathon ne chae",
GroupName: "I feel it in the earth",
},
},
},
} {
t.Run(name, func(t *testing.T) {
if got, err := a.getGroups(test.token); err != nil || !reflect.DeepEqual(got, test.groups) {
t.Errorf("expected %v, nil, got %v, %v", test.groups, got, err)
}
})
}
}
func TestDecodeHex(t *testing.T) {
t.Run("cantDecode", func(t *testing.T) {
_, err := decodeHex("gggg")
if err == nil {
t.Fatalf("expected err cannot decode slice, got nil")
}
})
t.Run("tooSmall", func(t *testing.T) {
_, err := decodeHex("DEADBEEF")
if err == nil {
t.Fatalf("expected err wrong length, got nil")
}
})
t.Run("tooBig", func(t *testing.T) {
_, err := decodeHex("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")
if err == nil {
t.Fatalf("expected err wrong length, got nil")
}
})
t.Run("justRight", func(t *testing.T) {
_, err := decodeHex("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")
if err != nil {
t.Fatalf("expected nil, got %v", err)
}
})
}
func TestHandlers(t *testing.T) {
a := NewTestAuth(t)
t.Run("login", func(t *testing.T) {
req := httptest.NewRequest("GET", "/login", nil)
w := httptest.NewRecorder()
a.Login(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusTemporaryRedirect {
t.Fatalf("expected redirect, got %v", resp.StatusCode)
}
redirect := a.oAuthConfig.AuthCodeURL(a.oAuthConfig.Endpoint.AuthURL)
if got, err := resp.Location(); err != nil || got.String() != redirect {
t.Fatalf("expected %v, got %v", redirect, got.Path)
}
})
t.Run("logout", func(t *testing.T) {
req := httptest.NewRequest("GET", "/logout", nil)
w := httptest.NewRecorder()
req.AddCookie(
&http.Cookie{
Name: a.accessCookieName,
Value: "test",
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: time.Unix(3000000, 0),
},
)
req.AddCookie(
&http.Cookie{
Name: a.refreshCookieName,
Value: "test",
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: time.Unix(3000000, 0),
},
)
a.groupsCache["test"] = cachedGroups{}
a.Logout(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusTemporaryRedirect {
t.Fatalf("expected redirect, got %v", resp.StatusCode)
}
redirect := fmt.Sprintf("%s?post_logout_redirect_uri=%s/", a.logoutEndpoint, a.fbURL)
if got, err := resp.Location(); err != nil || got.String() != redirect {
t.Fatalf("expected %v, got %v", redirect, got.Path)
}
for _, c := range resp.Cookies() {
if c.Name == a.accessCookieName || c.Name == a.refreshCookieName {
if c.Value != "" {
t.Fatalf("cookie not set to empty value!")
}
want := time.Unix(0, 0).Unix()
got := c.Expires.Unix()
if want != got {
t.Fatalf("expected %v, got %v", want, got)
}
}
}
if _, ok := a.groupsCache["test"]; ok {
t.Fatalf("groups not deleted!")
}
})
t.Run("redirectGood", func(t *testing.T) {
req := httptest.NewRequest("GET", "/redirect", nil)
w := httptest.NewRecorder()
tkn := jwt.New(jwt.SigningMethodHS256)
claims := tkn.Claims.(jwt.MapClaims)
claims["oid"] = "user id"
claims["name"] = "user name"
expiresIn := 2 * time.Hour
exp := time.Now().Add(expiresIn)
expiry := float64(exp.Unix())
claims["exp"] = expiry
fresh, err := tkn.SignedString(a.SecretKey())
if err != nil {
t.Fatalf("unexpected error when signing token %v", err)
}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body := `{"access_token": "` + fresh + `", "refresh_token": "blah", "expires_in": "` + strconv.Itoa(int(expiresIn.Seconds())) + `"}`
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(body))
}))
a.oAuthConfig.Endpoint.TokenURL = srv.URL
a.Redirect(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusTemporaryRedirect {
t.Fatalf("expected redirect, got %v", resp.StatusCode)
}
if got, err := resp.Location(); err != nil || got.String() != "/" {
t.Fatalf("expected %v, got %v", "/", got.Path)
}
cookies := resp.Cookies()
for _, c := range cookies {
if c.Name == a.accessCookieName && c.Value != fresh {
t.Fatalf("expected %v, got %v", exp, c.Value)
} else if c.Name == a.refreshCookieName && c.Value != "blah" {
t.Fatalf("expected %v, got %v", "blah", c.Value)
}
}
})
t.Run("redirectBad", func(t *testing.T) {
req := httptest.NewRequest("GET", "/redirect", nil)
w := httptest.NewRecorder()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Server Error", http.StatusInternalServerError)
}))
a.oAuthConfig.Endpoint.TokenURL = srv.URL
a.Redirect(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusBadRequest {
t.Fatalf("expected BadRequest, got %v", resp.StatusCode)
}
})
}
// This type is used for mocking ServerTransportStreams in tests
type ServerTransportStream struct {
md metadata.MD
method string
}
func NewServerTransportStream() *ServerTransportStream {
return &ServerTransportStream{
md: metadata.MD{},
method: "test",
}
}
func (s *ServerTransportStream) Method() string {
return s.method
}
func (s *ServerTransportStream) SetHeader(md metadata.MD) error {
s.md = md
return nil
}
func (s *ServerTransportStream) SendHeader(md metadata.MD) error {
_ = md
return nil
}
func (s *ServerTransportStream) SetTrailer(md metadata.MD) error {
_ = md
return nil
}
func TestCleanOAuthConfig(t *testing.T) {
a := NewTestAuth(t)
res := a.CleanOAuthConfig()
assertEqual("", res.ClientSecret, t)
assertEqual(a.oAuthConfig.ClientID, res.ClientID, t)
assertEqual(a.oAuthConfig.RedirectURL, res.RedirectURL, t)
assertEqual(a.oAuthConfig.Scopes, res.Scopes, t)
assertEqual(a.oAuthConfig.Endpoint, res.Endpoint, t)
}
func assertEqual(exp, got interface{}, t *testing.T) {
if !reflect.DeepEqual(exp, got) {
t.Fatalf("expected %v, got %v", exp, got)
}
}
func TestCheckAllowedNetworks(t *testing.T) {
tests := []struct {
requestIP string
configuredIPs []string
isAdmin bool
}{
{
requestIP: "10.0.0.1",
configuredIPs: []string{"10.0.0.1"},
isAdmin: true,
},
{
requestIP: "10.0.0.3",
configuredIPs: []string{"10.0.0.1", "10.0.0.2"},
isAdmin: false,
},
{
requestIP: "10.0.0.2",
configuredIPs: []string{"10.0.0.1/30"},
isAdmin: true,
},
// it is possible for the client IP to have a port
{
requestIP: "10.0.0.2:22",
configuredIPs: []string{"10.0.0.1/30"},
isAdmin: true,
},
{
requestIP: "10.1.0.3",
configuredIPs: []string{"10.0.0.1/32"},
isAdmin: false,
},
{
requestIP: "10.0.0.254",
configuredIPs: []string{"10.0.0.1/24"},
isAdmin: true,
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("network-%d", i), func(t *testing.T) {
a := NewTestAuth(t)
if err := a.convertIP(test.configuredIPs); err != nil {
t.Fatalf("failed to convert IPs from strings to net.IP: %v", err)
}
got := a.CheckAllowedNetworks(test.requestIP)
if got != test.isAdmin {
t.Fatalf("expected %v, got %v", test.isAdmin, got)
}
})
}
}
func TestConvertIP(t *testing.T) {
tests := []struct {
configuredIPs []string
convertedIPs []net.IPNet
}{
{
configuredIPs: []string{"10.0.0.1"},
convertedIPs: []net.IPNet{
{IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(32, 32)},
},
},
{
configuredIPs: []string{"10.0.0.1/30"},
convertedIPs: []net.IPNet{
{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(30, 32)},
},
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("network-%d", i), func(t *testing.T) {
a := NewTestAuth(t)
if err := a.convertIP(test.configuredIPs); err != nil {
t.Fatalf("failed to convert IPs from strings to net.IP: %v", err)
}
if len(a.allowedNetworks) != len(test.convertedIPs) {
t.Fatalf("expected len of %v networks, got %v", len(test.convertedIPs), len(a.allowedNetworks))
}
for i := range a.allowedNetworks {
expected, got := test.convertedIPs[i], a.allowedNetworks[i]
if got.IP.String() != expected.IP.String() {
t.Fatalf("for IP, expected %v, got %v", expected.IP, got.IP)
}
if got.Mask.String() != expected.Mask.String() {
t.Fatalf("for mask, expected %v, got %v", expected.Mask.String(), got.Mask.String())
}
}
})
}
}

54
authn/context.go Normal file
View file

@ -0,0 +1,54 @@
// Copyright 2022 Molecula Corp (DBA FeatureBase). All rights reserved.
package authn
import "context"
// Empty struct to avoid allocations
type contextKeyAccessToken struct{}
type contextKeyRefreshToken struct{}
type contextKeyUserInfo struct{}
type contextKeyIndexes struct{}
// GetAccessToken gets the access token from a context.
func GetAccessToken(ctx context.Context) (token string, ok bool) {
token, ok = ctx.Value(contextKeyAccessToken{}).(string)
return
}
// WithAccessToken makes a new Context with an access token.
func WithAccessToken(ctx context.Context, token string) context.Context {
return context.WithValue(ctx, contextKeyAccessToken{}, token)
}
// GetRefreshToken gets the refresh token from a context.
func GetRefreshToken(ctx context.Context) (token string, ok bool) {
token, ok = ctx.Value(contextKeyRefreshToken{}).(string)
return
}
// WithRefreshToken makes a new Context with a refresh token.
func WithRefreshToken(ctx context.Context, token string) context.Context {
return context.WithValue(ctx, contextKeyRefreshToken{}, token)
}
// GetUserInfo gets the UserInfo from a context.
func GetUserInfo(ctx context.Context) (userInfo *UserInfo, ok bool) {
userInfo, ok = ctx.Value(contextKeyUserInfo{}).(*UserInfo)
return
}
// WithUserInfo makes a new Context with UserInfo.
func WithUserInfo(ctx context.Context, userInfo *UserInfo) context.Context {
return context.WithValue(ctx, contextKeyUserInfo{}, userInfo)
}
// GetIndexes get the indices from a context.
func GetIndexes(ctx context.Context) (indexes []string, ok bool) {
indexes, ok = ctx.Value(contextKeyIndexes{}).([]string)
return
}
// WithIndexes makes a new Context with a []string containing the indicies.
func WithIndexes(ctx context.Context, indexes []string) context.Context {
return context.WithValue(ctx, contextKeyUserInfo{}, indexes)
}

130
authz/authorization.go Normal file
View file

@ -0,0 +1,130 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package authz
import (
"fmt"
"io"
"github.com/featurebasedb/featurebase/v3/authn"
"gopkg.in/yaml.v2"
)
type GroupPermissions struct {
Permissions map[string]map[string]Permission `yaml:"user-groups"`
Admin string `yaml:"admin"`
}
type Permission string
const (
None Permission = ""
Read Permission = "read"
Write Permission = "write"
Admin Permission = "admin"
)
// Satisfies returns whether `p` satisfies the permissions required by `b`
func (p Permission) Satisfies(b Permission) bool {
switch p {
case "":
return b == ""
case "read":
return b == "" || b == "read"
case "write":
return b == "" || b == "read" || b == "write"
case "admin":
return b == "" || b == "read" || b == "write" || b == "admin"
}
return false
}
func (p *GroupPermissions) ReadPermissionsFile(permsFile io.Reader) (err error) {
permsData, err := io.ReadAll(permsFile)
if err != nil {
return fmt.Errorf("reading permissions failed with error: %s", err)
}
err = yaml.UnmarshalStrict(permsData, &p)
if err != nil {
return fmt.Errorf("unmarshalling permissions failed with error: %s", err)
}
return
}
func (p *GroupPermissions) GetPermissions(user *authn.UserInfo, index string) (permission Permission, errors error) {
groups := user.Groups
if admin := p.IsAdmin(groups); admin {
return Admin, nil
}
allPermissions := map[Permission]bool{
Write: false,
Read: false,
}
if len(groups) == 0 {
return None, fmt.Errorf("user is not part of any groups in identity provider")
}
var groupsDenied []string
for _, group := range groups {
if _, ok := p.Permissions[group.GroupID]; ok {
if perm, ok := p.Permissions[group.GroupID][index]; ok {
allPermissions[perm] = true
} else {
return None, fmt.Errorf("user %s does not have permission to index %s", user.UserID, index)
}
} else {
groupsDenied = append(groupsDenied, group.GroupID)
}
}
if len(groupsDenied) == len(groups) {
return None, fmt.Errorf("group(s) %s does not have permission to FeatureBase", groupsDenied)
}
if allPermissions[Write] {
return Write, nil
} else if allPermissions[Read] {
return Read, nil
} else {
return None, fmt.Errorf("no permissions found")
}
}
func (p *GroupPermissions) IsAdmin(groups []authn.Group) bool {
for _, group := range groups {
if p.Admin == group.GroupID {
return true
}
}
return false
}
func (p *GroupPermissions) GetAuthorizedIndexList(groups []authn.Group, desiredPermission Permission) (indexList []string) {
// if user is admin, find all indexes in permissions file and return them
if p.IsAdmin(groups) {
for groupId := range p.Permissions {
for index := range p.Permissions[groupId] {
indexList = append(indexList, index)
}
}
return indexList
}
for _, group := range groups {
if _, ok := p.Permissions[group.GroupID]; ok {
for index, permission := range p.Permissions[group.GroupID] {
if permission.Satisfies(desiredPermission) {
indexList = append(indexList, index)
}
}
}
}
return indexList
}

305
authz/authorization_test.go Normal file
View file

@ -0,0 +1,305 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package authz_test
import (
"fmt"
"reflect"
"sort"
"strings"
"testing"
"github.com/featurebasedb/featurebase/v3/authn"
"github.com/featurebasedb/featurebase/v3/authz"
)
func TestAuth_ReadPermissionsFile(t *testing.T) {
singleInput := `user-groups:
"dca35310-ecda-4f23-86cd-876aee55906b":
"test": "read"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
multiInput := `user-groups:
"dca35310-ecda-4f23-86cd-876aee55906b":
"test": "read"
"test2": "write"
"dca35310-ecda-4f23-86cd-876aee559900":
"test": "write"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
singlePermission := authz.GroupPermissions{
Permissions: map[string]map[string]authz.Permission{
"dca35310-ecda-4f23-86cd-876aee55906b": {"test": authz.Read},
},
Admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
}
multiPermission := authz.GroupPermissions{
Permissions: map[string]map[string]authz.Permission{
"dca35310-ecda-4f23-86cd-876aee55906b": {"test": authz.Read, "test2": authz.Write},
"dca35310-ecda-4f23-86cd-876aee559900": {"test": authz.Write}},
Admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
}
tests := []struct {
input string
output authz.GroupPermissions
}{
{singleInput, singlePermission},
{multiInput, multiPermission},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
permFile := strings.NewReader(test.input)
var p authz.GroupPermissions
err := p.ReadPermissionsFile(permFile)
if err != nil {
t.Fatalf("readPermissionsFile error: %s", err)
}
if !reflect.DeepEqual(p, test.output) {
t.Fatalf("expected output %s, but got %s", test.output, p)
}
},
)
}
}
func TestAuth_GetPermissions(t *testing.T) {
// initializes different example of permissions file in yaml
permissions1 := `"user-groups":
"dca35310-ecda-4f23-86cd-876aee55906b":
"test": "read"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
permissions2 := `"user-groups":
"dca35310-ecda-4f23-86cd-876aee559900":
"test": "write"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
permissions3 := `"user-groups":
"dca35310-ecda-4f23-86cd-876aee55906b":
"test": "write"
"test2": "read"
"dca35310-ecda-4f23-86cd-876aee559900":
"test": "read"
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
permissions4 := `"user-groups":
"dca35310-ecda-4f23-86cd-876aee559900":
"test": ""
admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe"`
// initializes groups that are returned from identity provider
groupName := "name"
groupsList1 := []authn.Group{}
groupsList2 := []authn.Group{{
GroupID: "fake-group",
GroupName: groupName}}
groupsList3 := []authn.Group{
{GroupID: "dca35310-ecda-4f23-86cd-876aee55906b", GroupName: groupName},
{GroupID: "dca35310-ecda-4f23-86cd-876aee559900", GroupName: groupName},
}
groupsList4 := []authn.Group{{GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe", GroupName: groupName}}
tests := []struct {
yamlData string
groups []authn.Group
index string
userAccess authz.Permission
err string
}{
{
permissions1,
groupsList1,
"test",
authz.None,
"user is not part of any groups in identity provider",
},
{
permissions1,
groupsList3,
"test1",
authz.None,
"does not have permission to index",
},
{
permissions2,
groupsList2,
"test",
authz.None,
"does not have permission to FeatureBase",
},
{
permissions1,
groupsList3,
"test",
authz.Read,
"",
},
{
permissions2,
groupsList3,
"test",
authz.Write,
"",
},
{
permissions3,
groupsList4,
"test",
authz.Admin,
"",
},
{
permissions4,
groupsList3,
"test",
authz.None,
"no permissions found",
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
permFile := strings.NewReader(test.yamlData)
var p authz.GroupPermissions
if err := p.ReadPermissionsFile(permFile); err != nil {
t.Errorf("Error: %s", err)
}
p1, err := p.GetPermissions(&authn.UserInfo{Groups: test.groups}, test.index)
if p1 != test.userAccess {
t.Errorf("expected permission to be %s, but got %s", test.userAccess, p1)
}
if err != nil {
if !strings.Contains(err.Error(), test.err) {
t.Errorf("expected error to contain %s, but got %s", test.err, err.Error())
}
}
})
}
}
func TestAuth_IsAdmin(t *testing.T) {
group1 := []authn.Group{
{GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe", GroupName: "admin-group"},
}
group2 := []authn.Group{
{GroupID: "dca35310-ecda-4f23-86cd-876aee55906b", GroupName: "group-name"},
}
groupPermissions := authz.GroupPermissions{
Permissions: map[string]map[string]authz.Permission{
"dca35310-ecda-4f23-86cd-876aee55906b": {"test": authz.Write},
},
Admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
}
tests := []struct {
groups []authn.Group
groupPermissions authz.GroupPermissions
output bool
}{
{
group1, groupPermissions, true,
},
{
group2, groupPermissions, false,
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
p := test.groupPermissions
resp := p.IsAdmin(test.groups)
if resp != test.output {
t.Errorf("expected %t, but got %t", test.output, resp)
}
})
}
}
func TestAuth_GetAuthorizedIndexList(t *testing.T) {
group1 := []authn.Group{
{GroupID: "dca35310-ecda-4f23-86cd-876aee55906b", GroupName: "group-name"},
}
group2 := []authn.Group{
{GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe", GroupName: "admin-group"},
}
group3 := []authn.Group{
{GroupID: "dca35310-ecda-4f23-86cd-876aee559900", GroupName: "group-name"},
}
p := authz.GroupPermissions{
Permissions: map[string]map[string]authz.Permission{
"dca35310-ecda-4f23-86cd-876aee55906b": {
"test1": authz.Read,
"test2": authz.Write,
},
"dca35310-ecda-4f23-86cd-876aee559900": {
"test3": authz.Read,
},
},
Admin: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
}
tests := []struct {
groups []authn.Group
permission authz.Permission
output []string
}{
{
group1,
authz.Read,
[]string{"test1", "test2"},
},
{
group1,
authz.Write,
[]string{"test2"},
},
{
group3,
authz.Write,
nil,
},
{
group2,
authz.Read,
[]string{"test1", "test2", "test3"},
},
{
group2,
authz.Write,
[]string{"test1", "test2", "test3"},
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
indexList := p.GetAuthorizedIndexList(test.groups, test.permission)
sort.Strings(indexList)
if !reflect.DeepEqual(indexList, test.output) {
t.Errorf("expected %s, but got %s", test.output, indexList)
}
})
}
}

11
batch/Dockerfile-test Normal file
View file

@ -0,0 +1,11 @@
ARG GO_VERSION=1.19
FROM golang:${GO_VERSION}
WORKDIR /go/src/github.com/featurebasedb/featurebase/
COPY . .
WORKDIR /go/src/github.com/featurebasedb/featurebase/batch/
CMD ["go","test","-v","-mod=vendor","-tags=odbc,dynamic","./..."]

8
batch/Dockerfile-wait Normal file
View file

@ -0,0 +1,8 @@
FROM ubuntu:18.04
RUN ["apt-get", "update", "-y"]
RUN ["apt-get", "install", "-y", "curl", "netcat"]
ADD wait.sh /wait
ENTRYPOINT ["/wait"]

44
batch/Makefile Normal file
View file

@ -0,0 +1,44 @@
GO ?= go
# We allow setting a custom docker-compose "project". Multiple of the
# same docker-compose environment can exist simultaneously as long as
# they use different projects (the project name is prepended to
# container names and such). This is useful in a CI environment where
# we might be running multiple instances of the tests concurrently.
PROJECT ?= batch
DOCKER_COMPOSE = docker-compose -p $(PROJECT)
vendor: ../go.mod
$(GO) mod vendor
build-%:
$(DOCKER_COMPOSE) build $*
test-all:
$(MAKE) startup
$(MAKE) test-run
$(MAKE) shutdown
start-all: build-wait
$(DOCKER_COMPOSE) up -d featurebase
$(DOCKER_COMPOSE) run -T wait featurebase curl --silent --fail http://featurebase:10101/status
startup: start-all
shutdown:
$(DOCKER_COMPOSE) down -v --remove-orphans
save-%-logs:
$(DOCKER_COMPOSE) logs $* > ./testdata/$(PROJECT)_$*_logs.txt
TCMD ?= ./...
# do "make startup", then e.g. "make test-run-local TCMD='-run=MyFavTest ./kafka'"
test-run-local: vendor
pwd
$(DOCKER_COMPOSE) build batch-test
$(DOCKER_COMPOSE) run -T batch-test go test -mod=vendor -tags=odbc,dynamic $(TCMD)
TPKG ?= ../...
test-run: vendor
$(DOCKER_COMPOSE) build batch-test
$(DOCKER_COMPOSE) run -T batch-test bash -c "set -o pipefail; go test -v -mod=vendor -tags=odbc,dynamic ./... -covermode=atomic -coverpkg=$(TPKG) -coverprofile=/testdata/$(PROJECT)_base_coverage.out"

46
batch/README.md Normal file
View file

@ -0,0 +1,46 @@
# batch
The `batch` package provides a standard tool set for batching records in a way
that is most performant for ingesting those records into FeatureBase. The main
implementation is `Batch` (which can be initated with the `NewBatch()`
function). The `NewBatch()` function takes an `Importer` which contains all of
the methods required to interact with FeatureBase; these include methods for
doing string/id translation as well as for importing shards of data.
IDK uses the `batch` package internally. Another example where the `batch`
package is used in the `sql3` package. When an "INSERT INTO" statement is
executed, the SQL engine uses a `Batch` to do key translation and build import
batches prior to doing the final import.
## Integration tests
To run the tests, you will need to install the following dependencies:
1. [Docker](https://docs.docker.com/install/)
2. [Docker Compose](https://docs.docker.com/compose/install/)
In addition to these dependancies, you will need to be added to the molecula [Gitlab](https://registry.gitlab.com/molecula) account.
First start the test environment. This is a docker-compose environment that includes featurebase.
make startup
To build and run the integration tests, run:
make test-run-local
Then to shut down the test environment, run:
make shutdown
The previous command is equivalent to running the following:
make startup
sleep 30 # wait for services to come up
make test-run
make shutdown
To run an individual test, you can run the command directly using docker-compose. Note that you must run `docker-compose build batch-test` for docker to run the latest code. Modify the following as needed:
make startup
docker-compose build batch-test
docker-compose run batch-test /usr/local/go/bin/go test -count=1 -mod=vendor -run=TestCmdMainOne .

2001
batch/batch.go Normal file

File diff suppressed because it is too large Load diff

2413
batch/batch_test.go Normal file

File diff suppressed because it is too large Load diff

20
batch/batcher.go Normal file
View file

@ -0,0 +1,20 @@
package batch
import (
"time"
"github.com/featurebasedb/featurebase/v3/dax"
)
// Batcher is an interface implemented by anything which can allocate new
// batches.
type Batcher interface {
NewBatch(cfg Config, tbl *dax.Table, fields []*dax.Field) (RecordBatch, error)
}
// Config is the configuration options passed to NewBatch for any implementation
// of the Batcher interface.
type Config struct {
Size int
MaxStaleness time.Duration
}

145
batch/convert.go Normal file
View file

@ -0,0 +1,145 @@
package batch
import (
"time"
featurebase "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/errors"
)
var (
MinTimestampNano = time.Unix(-1<<32, 0).UTC() // 1833-11-24T17:31:44Z
MaxTimestampNano = time.Unix(1<<32, 0).UTC() // 2106-02-07T06:28:16Z
MinTimestamp = time.Unix(-62135596799, 0).UTC() // 0001-01-01T00:00:01Z
MaxTimestamp = time.Unix(253402300799, 0).UTC() // 9999-12-31T23:59:59Z
ErrTimestampOutOfRange = errors.New("", "value provided for timestamp field is out of range")
)
type TimeUnit string
const (
TimeUnitSeconds = TimeUnit(featurebase.TimeUnitSeconds)
TimeUnitMilliseconds = TimeUnit(featurebase.TimeUnitMilliseconds)
TimeUnitMicroseconds = TimeUnit(featurebase.TimeUnitMicroseconds)
TimeUnitUSeconds = TimeUnit(featurebase.TimeUnitUSeconds)
TimeUnitNanoseconds = TimeUnit(featurebase.TimeUnitNanoseconds)
)
// TimestampToInt64 converts the provided timestamp to an int64 as the number of
// units past the epoch.
func TimestampToInt64(unit TimeUnit, epoch time.Time, ts time.Time) (int64, error) {
var err error
unit, err = validateTimeUnit(unit)
if err != nil {
return 0, errors.Wrap(err, "validating time unit")
}
epoch, err = validateEpoch(epoch)
if err != nil {
return 0, errors.Wrap(err, "validating epoch")
}
// Check if the epoch alone is out-of-range. If so, ingest should halt,
// regardless of state of the timestamp out-of-range CLI option.
if err := validateTimestamp(unit, epoch); err != nil {
return 0, errors.Wrap(err, "validating epoch")
}
epochAsInt64 := timestampToInt(unit, epoch)
// Check if the timestamp is out-of-range.
if err := validateTimestamp(unit, ts); err != nil {
return 0, errors.Wrapf(ErrTimestampOutOfRange, "validating timestamp: %s", ts)
}
tsAsInt64 := timestampToInt(unit, ts)
return tsAsInt64 - epochAsInt64, nil
}
// validateTimeUnit checks if the time unit is supported. If the provided unit
// is blank, validateTimeUnit returns the default TimeUnit.
func validateTimeUnit(unit TimeUnit) (TimeUnit, error) {
switch unit {
case "":
return TimeUnitSeconds, nil
case TimeUnitSeconds,
TimeUnitMilliseconds,
TimeUnitMicroseconds,
TimeUnitUSeconds,
TimeUnitNanoseconds:
return unit, nil
}
return "", errors.Errorf("unsupported time unit: %s", unit)
}
// validateEpoch checks if the epoch is supported. If the provided epoch
// is "zero", validateEpoch returns the default epoch value.
func validateEpoch(epoch time.Time) (time.Time, error) {
if epoch.IsZero() {
return time.Unix(0, 0), nil
}
return epoch, nil
}
// validateTimestamp checks if the timestamp is within the range of what FB accepts.
func validateTimestamp(unit TimeUnit, ts time.Time) error {
// Min and Max timestamps that Featurebase accepts
var minStamp, maxStamp time.Time
switch unit {
case TimeUnitNanoseconds:
minStamp = MinTimestampNano
maxStamp = MaxTimestampNano
default:
minStamp = MinTimestamp
maxStamp = MaxTimestamp
}
if ts.Before(minStamp) || ts.After(maxStamp) {
return errors.Errorf("timestamp value (%v) must be within min: %v and max: %v", ts, minStamp, maxStamp)
}
return nil
}
// timestampToInt takes a time unit and a time.Time and converts it to an
// integer value.
func timestampToInt(unit TimeUnit, ts time.Time) int64 {
switch unit {
case TimeUnitSeconds:
return ts.Unix()
case TimeUnitMilliseconds:
return ts.UnixMilli()
case TimeUnitMicroseconds, TimeUnitUSeconds:
return ts.UnixMicro()
case TimeUnitNanoseconds:
return ts.UnixNano()
}
return 0
}
// intToTimestamp takes a timeunit and an integer value and converts it to
// time.Time.
func intToTimestamp(unit TimeUnit, val int64) (time.Time, error) {
switch unit {
case TimeUnitSeconds:
return time.Unix(val, 0).UTC(), nil
case TimeUnitMilliseconds:
return time.UnixMilli(val).UTC(), nil
case TimeUnitMicroseconds, TimeUnitUSeconds:
return time.UnixMicro(val).UTC(), nil
case TimeUnitNanoseconds:
return time.Unix(0, val).UTC(), nil
default:
return time.Time{}, errors.Errorf("Unknown time unit: '%v'", unit)
}
}
// Int64ToTimestamp converts the provided int64 to a timestamp based on the time unit
// and epoch.
func Int64ToTimestamp(unit TimeUnit, epoch time.Time, val int64) (time.Time, error) {
return intToTimestamp(unit, timestampToInt(unit, epoch)+val)
}

29
batch/docker-compose.yml Normal file
View file

@ -0,0 +1,29 @@
version: '3'
services:
featurebase:
build:
context: ../.
dockerfile: ./Dockerfile-clustertests
environment:
PILOSA_DATA_DIR: /data
PILOSA_BIND: 0.0.0.0:10101
PILOSA_BIND_GRPC: 0.0.0.0:20101
PILOSA_ADVERTISE: featurebase:10101
command: /featurebase -test.run=TestRunMain -test.coverprofile=/testdata/batch_coverage.out server
volumes:
- ./testdata:/testdata
batch-test:
build:
context: ../.
dockerfile: ./batch/Dockerfile-test
volumes:
- ./testdata:/testdata
wait:
depends_on:
- "featurebase"
build:
context: .
dockerfile: Dockerfile-wait

111
batch/egpool/egpool.go Normal file
View file

@ -0,0 +1,111 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package egpool
import (
"errors"
"fmt"
"sync"
)
type Group struct {
PoolSize int
jobs chan func() error
sema chan struct{}
errMu sync.Mutex
firstErr error
errs []error
}
func (eg *Group) Go(f func() error) {
if eg.PoolSize <= 0 {
eg.PoolSize = 1
}
if eg.jobs == nil {
eg.jobs = make(chan func() error)
eg.sema = make(chan struct{}, eg.PoolSize)
}
// Start the job in an idle worker if possible.
select {
case eg.jobs <- f:
return
default:
}
// Start a new worker if necessary.
select {
case eg.jobs <- f:
// A worker finished its previous job and took this one over.
return
case eg.sema <- struct{}{}:
// Start a new worker.
go eg.processJobs()
eg.jobs <- f
}
}
func (eg *Group) err(err error) {
eg.errMu.Lock()
defer eg.errMu.Unlock()
if eg.firstErr == nil {
eg.firstErr = err
}
eg.errs = append(eg.errs, err)
}
type PanicError struct {
Value interface{}
}
func (p PanicError) Error() string {
return fmt.Sprintf("panic: %v", p.Value)
}
var ErrGoexit = errors.New("runtime.Goexit used in job function")
func (eg *Group) processJobs() {
// Notify pool of shutdown.
defer func() { <-eg.sema }()
// Handle panic and Goexit.
var finished bool
defer func() {
if !finished {
if p := recover(); p != nil {
eg.err(PanicError{p})
} else {
eg.err(ErrGoexit)
}
}
}()
// Run jobs from queue.
for jobFn := range eg.jobs {
err := jobFn()
if err != nil {
eg.err(err)
}
}
finished = true
}
func (eg *Group) Wait() error {
if eg.jobs == nil {
return nil
}
close(eg.jobs)
for i := 0; i < eg.PoolSize; i++ {
eg.sema <- struct{}{}
}
return eg.firstErr
}
func (eg *Group) Errors() []error {
return eg.errs
}

View file

@ -0,0 +1,38 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package egpool_test
import (
"errors"
"testing"
"github.com/featurebasedb/featurebase/v3/batch/egpool"
)
func TestEGPool(t *testing.T) {
eg := egpool.Group{}
a := make([]int, 10)
for i := 0; i < 10; i++ {
i := i
eg.Go(func() error {
a[i] = i
if i == 7 {
return errors.New("blah")
}
return nil
})
}
err := eg.Wait()
if err == nil || err.Error() != "blah" {
t.Errorf("expected err blah, got: %v", err)
}
for i := 0; i < 10; i++ {
if a[i] != i {
t.Errorf("expected a[%d] to be %d, but is %d", i, i, a[i])
}
}
}

8
batch/error.go Normal file
View file

@ -0,0 +1,8 @@
package batch
import "github.com/pkg/errors"
// Predefined batch-related errors.
var (
ErrPreconditionFailed = errors.New("Precondition failed")
)

3
batch/metrics.go Normal file
View file

@ -0,0 +1,3 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package batch

3
batch/testdata/README.md vendored Normal file
View file

@ -0,0 +1,3 @@
# testdata
This directory is used in CI tests. I think.

26
batch/wait.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/sh
name=$1
shift
_start_ts=$(date +%s)
elapsed=0
timeout=120
while :
do
$@ > /dev/null
_ret=$?
_end_ts=$(date +%s)
if [ $_ret -eq 0 ]; then
echo "$name is available after $((_end_ts - _start_ts)) seconds."
break
else
echo "Waiting for $name after $((_end_ts - _start_ts)) seconds."
fi
sleep 1s
elapsed=$((elapsed+1))
if [ $elapsed -ge $timeout ]; then
exit 110
fi
done
set -ex

468
bitmap.go
View file

@ -1,468 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pilosa
// #cgo CFLAGS:-mpopcnt
import (
"encoding/json"
"sort"
"github.com/pilosa/pilosa/internal"
"github.com/pilosa/pilosa/roaring"
)
// Bitmap represents a set of bits.
type Bitmap struct {
segments []BitmapSegment
// Attributes associated with the bitmap.
Attrs map[string]interface{}
}
// NewBitmap returns a new instance of Bitmap.
func NewBitmap(bits ...uint64) *Bitmap {
bm := &Bitmap{}
for _, i := range bits {
bm.SetBit(i)
}
return bm
}
// Merge merges data from other into b.
func (b *Bitmap) Merge(other *Bitmap) {
var segments []BitmapSegment
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
// Use the other bitmap's data if segment is missing.
if s0 == nil {
segments = append(segments, *s1)
continue
} else if s1 == nil {
segments = append(segments, *s0)
continue
}
// Otherwise merge.
s0.Merge(s1)
segments = append(segments, *s0)
}
b.segments = segments
b.InvalidateCount()
}
// IntersectionCount returns the number of intersections between b and other.
func (b *Bitmap) IntersectionCount(other *Bitmap) uint64 {
var n uint64
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
// Ignore non-overlapping segments.
if s0 == nil || s1 == nil {
continue
}
n += s0.IntersectionCount(s1)
}
return n
}
// Intersect returns the itersection of b and other.
func (b *Bitmap) Intersect(other *Bitmap) *Bitmap {
var segments []BitmapSegment
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
// Ignore non-overlapping segments.
if s0 == nil || s1 == nil {
continue
}
segments = append(segments, *s0.Intersect(s1))
}
return &Bitmap{segments: segments}
}
// Xor returns the xor of b and other.
func (b *Bitmap) Xor(other *Bitmap) *Bitmap {
var segments []BitmapSegment
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
if s1 == nil {
segments = append(segments, *s0)
continue
} else if s0 == nil {
segments = append(segments, *s1)
continue
}
segments = append(segments, *s0.Xor(s1))
}
return &Bitmap{segments: segments}
}
// Union returns the bitwise union of b and other.
func (b *Bitmap) Union(other *Bitmap) *Bitmap {
var segments []BitmapSegment
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
if s1 == nil {
segments = append(segments, *s0)
continue
} else if s0 == nil {
segments = append(segments, *s1)
continue
}
segments = append(segments, *s0.Union(s1))
}
return &Bitmap{segments: segments}
}
// Difference returns the diff of b and other.
func (b *Bitmap) Difference(other *Bitmap) *Bitmap {
var segments []BitmapSegment
itr := newMergeSegmentIterator(b.segments, other.segments)
for s0, s1 := itr.next(); s0 != nil || s1 != nil; s0, s1 = itr.next() {
if s0 == nil {
continue
} else if s1 == nil {
segments = append(segments, *s0)
continue
}
segments = append(segments, *s0.Difference(s1))
}
return &Bitmap{segments: segments}
}
// SetBit sets the i-th bit of the bitmap.
func (b *Bitmap) SetBit(i uint64) (changed bool) {
return b.createSegmentIfNotExists(i / SliceWidth).SetBit(i)
}
// ClearBit clears the i-th bit of the bitmap.
func (b *Bitmap) ClearBit(i uint64) (changed bool) {
s := b.segment(i / SliceWidth)
if s == nil {
return false
}
return s.ClearBit(i)
}
// segment returns a segment for a given slice.
// Returns nil if segment does not exist.
func (b *Bitmap) segment(slice uint64) *BitmapSegment {
if i := sort.Search(len(b.segments), func(i int) bool {
return b.segments[i].slice >= slice
}); i < len(b.segments) && b.segments[i].slice == slice {
return &b.segments[i]
}
return nil
}
func (b *Bitmap) createSegmentIfNotExists(slice uint64) *BitmapSegment {
i := sort.Search(len(b.segments), func(i int) bool {
return b.segments[i].slice >= slice
})
// Return exact match.
if i < len(b.segments) && b.segments[i].slice == slice {
return &b.segments[i]
}
// Insert new segment.
b.segments = append(b.segments, BitmapSegment{})
if i < len(b.segments) {
copy(b.segments[i+1:], b.segments[i:])
}
b.segments[i] = BitmapSegment{
slice: slice,
writable: true,
}
return &b.segments[i]
}
// InvalidateCount updates the cached count in the bitmap.
func (b *Bitmap) InvalidateCount() {
for i := range b.segments {
b.segments[i].InvalidateCount()
}
}
// IncrementCount increments the bitmap cached counter, note this is an optimization that assumes that the caller is aware the size increased.
func (b *Bitmap) IncrementCount(i uint64) {
seg := b.segment(i / SliceWidth)
if seg != nil {
seg.n++
}
}
// DecrementCount decrements the bitmap cached counter.
func (b *Bitmap) DecrementCount(i uint64) {
seg := b.segment(i / SliceWidth)
if seg != nil {
if seg.n > 0 {
seg.n--
}
}
}
// Count returns the number of set bits in the bitmap.
func (b *Bitmap) Count() uint64 {
var n uint64
for i := range b.segments {
n += b.segments[i].Count()
}
return n
}
// MarshalJSON returns a JSON-encoded byte slice of b.
func (b *Bitmap) MarshalJSON() ([]byte, error) {
var o struct {
Attrs map[string]interface{} `json:"attrs"`
Bits []uint64 `json:"bits"`
}
o.Bits = b.Bits()
o.Attrs = b.Attrs
if o.Attrs == nil {
o.Attrs = make(map[string]interface{})
}
return json.Marshal(&o)
}
// Bits returns the bits in b as a slice of ints.
func (b *Bitmap) Bits() []uint64 {
a := make([]uint64, 0, b.Count())
for i := range b.segments {
a = append(a, b.segments[i].Bits()...)
}
return a
}
// encodeBitmap converts b into its internal representation.
func encodeBitmap(b *Bitmap) *internal.Bitmap {
if b == nil {
return nil
}
return &internal.Bitmap{
Bits: b.Bits(),
Attrs: encodeAttrs(b.Attrs),
}
}
// decodeBitmap converts b from its internal representation.
func decodeBitmap(pb *internal.Bitmap) *Bitmap {
if pb == nil {
return nil
}
b := NewBitmap()
b.Attrs = decodeAttrs(pb.Attrs)
for _, v := range pb.Bits {
b.SetBit(v)
}
return b
}
// Union performs a union on a slice of bitmaps.
func Union(bitmaps []*Bitmap) *Bitmap {
other := bitmaps[0]
for _, bm := range bitmaps[1:] {
other = other.Union(bm)
}
return other
}
// BitmapSegment holds a subset of a bitmap.
// This could point to a mmapped roaring bitmap or an in-memory bitmap. The
// width of the segment will always match the slice width.
type BitmapSegment struct {
// Slice this segment belongs to
slice uint64
// Underlying raw bitmap implementation.
// This is an mmapped bitmap if writable is false. Otherwise
// it is a heap allocated bitmap which can be manipulated.
data roaring.Bitmap
writable bool
// Bit count
n uint64
}
// Merge adds chunks from other to s.
// Chunks in s are overwritten if they exist in other.
func (s *BitmapSegment) Merge(other *BitmapSegment) {
s.ensureWritable()
itr := other.data.Iterator()
for v, eof := itr.Next(); !eof; v, eof = itr.Next() {
s.SetBit(v)
}
}
// IntersectionCount returns the number of intersections between s and other.
func (s *BitmapSegment) IntersectionCount(other *BitmapSegment) uint64 {
return s.data.IntersectionCount(&other.data)
}
// Intersect returns the itersection of s and other.
func (s *BitmapSegment) Intersect(other *BitmapSegment) *BitmapSegment {
data := s.data.Intersect(&other.data)
return &BitmapSegment{
data: *data,
slice: s.slice,
n: data.Count(),
}
}
// Union returns the bitwise union of s and other.
func (s *BitmapSegment) Union(other *BitmapSegment) *BitmapSegment {
data := s.data.Union(&other.data)
return &BitmapSegment{
data: *data,
slice: s.slice,
n: data.Count(),
}
}
// Difference returns the diff of s and other.
func (s *BitmapSegment) Difference(other *BitmapSegment) *BitmapSegment {
data := s.data.Difference(&other.data)
return &BitmapSegment{
data: *data,
slice: s.slice,
n: data.Count(),
}
}
// Xor returns the xor of s and other.
func (s *BitmapSegment) Xor(other *BitmapSegment) *BitmapSegment {
data := s.data.Xor(&other.data)
return &BitmapSegment{
data: *data,
slice: s.slice,
n: data.Count(),
}
}
// SetBit sets the i-th bit of the bitmap.
func (s *BitmapSegment) SetBit(i uint64) (changed bool) {
s.ensureWritable()
changed, _ = s.data.Add(i)
if changed {
s.n++
}
return changed
}
// ClearBit clears the i-th bit of the bitmap.
func (s *BitmapSegment) ClearBit(i uint64) (changed bool) {
s.ensureWritable()
changed, _ = s.data.Remove(i)
if changed {
s.n--
}
return changed
}
// InvalidateCount updates the cached count in the bitmap.
func (s *BitmapSegment) InvalidateCount() {
s.n = s.data.Count()
}
// Bits returns a list of all bits set in the segment.
func (s *BitmapSegment) Bits() []uint64 {
a := make([]uint64, 0, s.Count())
itr := s.data.Iterator()
for v, eof := itr.Next(); !eof; v, eof = itr.Next() {
a = append(a, v)
}
return a
}
// Count returns the number of set bits in the bitmap.
func (s *BitmapSegment) Count() uint64 { return s.n }
// ensureWritable clones the segment if it is pointing to non-writable data.
func (s *BitmapSegment) ensureWritable() {
if s.writable {
return
}
s.data = *s.data.Clone()
s.writable = true
}
// mergeSegmentIterator produces an iterator that loops through two sets of segments.
type mergeSegmentIterator struct {
a0, a1 []BitmapSegment
}
// newMergeSegmentIterator returns a new instance of mergeSegmentIterator.
func newMergeSegmentIterator(a0, a1 []BitmapSegment) mergeSegmentIterator {
return mergeSegmentIterator{a0: a0, a1: a1}
}
// next returns the next set of segments.
func (itr *mergeSegmentIterator) next() (s0, s1 *BitmapSegment) {
// Find current segments.
if len(itr.a0) > 0 {
s0 = &itr.a0[0]
}
if len(itr.a1) > 0 {
s1 = &itr.a1[0]
}
// Return if either or both are nil.
if s0 == nil && s1 == nil {
return
} else if s0 == nil {
itr.a1 = itr.a1[1:]
return
} else if s1 == nil {
itr.a0 = itr.a0[1:]
return
}
// Otherwise determine which is first.
if s0.slice < s1.slice {
itr.a0 = itr.a0[1:]
return s0, nil
} else if s0.slice > s1.slice {
itr.a1 = itr.a1[1:]
return s1, nil
}
// Return both if slices are equal.
itr.a0, itr.a1 = itr.a0[1:], itr.a1[1:]
return s0, s1
}

View file

@ -1,92 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pilosa_test
import (
"reflect"
"testing"
"github.com/pilosa/pilosa"
)
// Ensure a bitmap can be merged
func TestBitmap_Merge(t *testing.T) {
bm1 := pilosa.NewBitmap(1, 2, 3, SliceWidth+1, 2*SliceWidth)
bm2 := pilosa.NewBitmap(3, 4, 5)
bm1.Merge(bm2)
if bm1.Count() != 7 {
t.Fatalf("Count after merge %d != 7\n", bm1.Count())
}
}
// Ensure a bitmap can Xor'ed
func TestBitmap_Xor(t *testing.T) {
bm1 := pilosa.NewBitmap(0, 1, SliceWidth)
bm2 := pilosa.NewBitmap(0, 2*SliceWidth)
exp := []uint64{1, SliceWidth, 2 * SliceWidth}
res := bm1.Xor(bm2)
if res.Count() != 3 {
t.Fatalf("Test 1 Count after xor %d != 3\n", res.Count())
}
if !reflect.DeepEqual(res.Bits(), exp) {
t.Fatalf("Test 2 Results %v != expected %v\n", res.Bits(), exp)
}
res = bm2.Xor(bm1)
if res.Count() != 3 {
t.Fatalf("Test 3 Count after xor %d != 3\n", res.Count())
}
if !reflect.DeepEqual(res.Bits(), exp) {
t.Fatalf("Test 4 Results %v != expected %v\n", res.Bits(), exp)
}
}
func TestBitmap_Union_Segment(t *testing.T) {
bm1 := pilosa.NewBitmap(0, 1, SliceWidth)
bm2 := pilosa.NewBitmap(0, 2*SliceWidth)
exp := []uint64{0, 1, SliceWidth, 2 * SliceWidth}
res := bm1.Union(bm2)
if res.Count() != 4 {
t.Fatalf("Test 1 Count after Union %d != 5\n", res.Count())
}
if !reflect.DeepEqual(res.Bits(), exp) {
t.Fatalf("Test 2 Union Results %v != expected %v\n", res.Bits(), exp)
}
res = bm2.Union(bm1)
if res.Count() != 4 {
t.Fatalf("Test 3 Count after xor %d != 5\n", res.Count())
}
if !reflect.DeepEqual(res.Bits(), exp) {
t.Fatalf("Test 2 Union Results %v != expected %v\n", res.Bits(), exp)
}
}
func TestBitmap_Difference_Segment(t *testing.T) {
bm1 := pilosa.NewBitmap(0, 1, SliceWidth)
bm2 := pilosa.NewBitmap(0, 2*SliceWidth)
exp := []uint64{1, SliceWidth}
res := bm1.Difference(bm2)
if res.Count() != 2 {
t.Fatalf("Test 1 Count after Difference %d != 5\n", res.Count())
}
if !reflect.DeepEqual(res.Bits(), exp) {
t.Fatalf("Test 2 Difference Results %v != expected %v\n", res.Bits(), exp)
}
}

View file

@ -1,181 +1,165 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"fmt"
"reflect"
"github.com/gogo/protobuf/proto"
"github.com/pilosa/pilosa/internal"
"github.com/featurebasedb/featurebase/v3/disco"
"github.com/pkg/errors"
)
// NodeSet represents an interface for Node membership and inter-node communication.
type NodeSet interface {
// Returns a list of all Nodes in the cluster
Nodes() []*Node
// Open starts any network activity implemented by the NodeSet
Open() error
// Serializer is an interface for serializing pilosa types to bytes and back.
type Serializer interface {
Marshal(Message) ([]byte, error)
Unmarshal([]byte, Message) error
}
// StaticNodeSet represents a basic NodeSet for testing.
type StaticNodeSet struct {
nodes []*Node
// NopSerializer represents a Serializer that doesn't do anything.
var NopSerializer Serializer = &nopSerializer{}
type nopSerializer struct{}
// Marshal is a no-op implementation of Serializer Marshal method.
func (*nopSerializer) Marshal(Message) ([]byte, error) { return nil, nil }
// Unmarshal is a no-op implementation of Serializer Unmarshal method.
func (*nopSerializer) Unmarshal([]byte, Message) error { return nil }
// broadcaster is an interface for broadcasting messages.
type broadcaster interface {
SendSync(Message) error
SendAsync(Message) error
SendTo(*disco.Node, Message) error
}
// NewStaticNodeSet creates a statically defined NodeSet.
func NewStaticNodeSet() *StaticNodeSet {
return &StaticNodeSet{}
}
// Nodes implements the NodeSet interface and returns a list of nodes in the cluster.
func (s *StaticNodeSet) Nodes() []*Node {
return s.nodes
}
// Open implements the NodeSet interface to start network activity, but for a static NodeSet it does nothing.
func (s *StaticNodeSet) Open() error {
return nil
}
// Join sets the NodeSet nodes to the slice of Nodes passed in.
func (s *StaticNodeSet) Join(nodes []*Node) error {
s.nodes = nodes
return nil
}
// Broadcaster is an interface for broadcasting messages.
type Broadcaster interface {
SendSync(pb proto.Message) error
SendAsync(pb proto.Message) error
}
func init() {
NopBroadcaster = &nopBroadcaster{}
}
// Message is the interface implemented by all core pilosa types which can be serialized to messages.
// TODO add at least a single "isMessage()" method.
type Message interface{}
// NopBroadcaster represents a Broadcaster that doesn't do anything.
var NopBroadcaster Broadcaster
var NopBroadcaster broadcaster = &nopBroadcaster{}
type nopBroadcaster struct{}
// SendSync A no-op implemenetation of Broadcaster SendSync method.
func (c *nopBroadcaster) SendSync(pb proto.Message) error {
return nil
}
// SendSync A no-op implementation of Broadcaster SendSync method.
func (nopBroadcaster) SendSync(Message) error { return nil }
// SendAsync A no-op implemenetation of Broadcaster SendAsync method.
func (c *nopBroadcaster) SendAsync(pb proto.Message) error {
return nil
}
// SendAsync A no-op implementation of Broadcaster SendAsync method.
func (nopBroadcaster) SendAsync(Message) error { return nil }
// BroadcastHandler is the interface for the pilosa object which knows how to
// handle broadcast messages. (Hint: this is implemented by pilosa.Server)
type BroadcastHandler interface {
ReceiveMessage(pb proto.Message) error
}
// BroadcastReceiver is the interface for the object which will listen for and
// decode broadcast messages before passing them to pilosa to handle. The
// implementation of this could be an http server which listens for messages,
// gets the protobuf payload, and then passes it to
// BroadcastHandler.ReceiveMessage.
type BroadcastReceiver interface {
// Start starts listening for broadcast messages - it should return
// immediately, spawning a goroutine if necessary.
Start(BroadcastHandler) error
}
type nopBroadcastReceiver struct{}
func (n *nopBroadcastReceiver) Start(b BroadcastHandler) error { return nil }
// NopBroadcastReceiver is a no-op implementation of the BroadcastReceiver.
var NopBroadcastReceiver = &nopBroadcastReceiver{}
// SendTo is a no-op implementation of Broadcaster SendTo method.
func (nopBroadcaster) SendTo(*disco.Node, Message) error { return nil }
// Broadcast message types.
const (
MessageTypeCreateSlice = 1
MessageTypeCreateIndex = 2
MessageTypeDeleteIndex = 3
MessageTypeCreateFrame = 4
MessageTypeDeleteFrame = 5
MessageTypeCreateInputDefinition = 6
MessageTypeDeleteInputDefinition = 7
MessageTypeDeleteView = 8
messageTypeCreateShard = iota
messageTypeCreateIndex
messageTypeDeleteIndex
messageTypeCreateField
messageTypeDeleteField
messageTypeCreateView
messageTypeDeleteView
messageTypeClusterStatus
messageTypeUNUSED0 // used to be ResizeInstruction
messageTypeUNUSED1 // used to be ResizeInstructionComplete
messageTypeNodeState
messageTypeRecalculateCaches
messageTypeLoadSchemaMessage
messageTypeNodeEvent
messageTypeNodeStatus
messageTypeTransaction
messageTypeUNUSED2 // used to be ResizeNodeMessage
messageTypeUNUSED3 // used to be ResizeAbortMessage
messageTypeUpdateField
messageTypeDeleteDataframe
)
// MarshalMessage encodes the protobuf message into a byte slice.
func MarshalMessage(m proto.Message) ([]byte, error) {
var typ uint8
switch obj := m.(type) {
case *internal.CreateSliceMessage:
typ = MessageTypeCreateSlice
case *internal.CreateIndexMessage:
typ = MessageTypeCreateIndex
case *internal.DeleteIndexMessage:
typ = MessageTypeDeleteIndex
case *internal.CreateFrameMessage:
typ = MessageTypeCreateFrame
case *internal.DeleteFrameMessage:
typ = MessageTypeDeleteFrame
case *internal.CreateInputDefinitionMessage:
typ = MessageTypeCreateInputDefinition
case *internal.DeleteInputDefinitionMessage:
typ = MessageTypeDeleteInputDefinition
case *internal.DeleteViewMessage:
typ = MessageTypeDeleteView
default:
return nil, fmt.Errorf("message type not implemented for marshalling: %s", reflect.TypeOf(obj))
}
buf, err := proto.Marshal(m)
// MarshalInternalMessage serializes the pilosa message and adds pilosa internal
// type info which is used by the internal messaging stuff.
func MarshalInternalMessage(m Message, s Serializer) ([]byte, error) {
typ := getMessageType(m)
buf, err := s.Marshal(m)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "marshaling")
}
return append([]byte{typ}, buf...), nil
}
// UnmarshalMessage decodes the byte slice into a protobuf message.
func UnmarshalMessage(buf []byte) (proto.Message, error) {
typ, buf := buf[0], buf[1:]
var m proto.Message
func getMessage(typ byte) Message {
switch typ {
case MessageTypeCreateSlice:
m = &internal.CreateSliceMessage{}
case MessageTypeCreateIndex:
m = &internal.CreateIndexMessage{}
case MessageTypeDeleteIndex:
m = &internal.DeleteIndexMessage{}
case MessageTypeCreateFrame:
m = &internal.CreateFrameMessage{}
case MessageTypeDeleteFrame:
m = &internal.DeleteFrameMessage{}
case MessageTypeCreateInputDefinition:
m = &internal.CreateInputDefinitionMessage{}
case MessageTypeDeleteInputDefinition:
m = &internal.DeleteInputDefinitionMessage{}
case MessageTypeDeleteView:
m = &internal.DeleteViewMessage{}
case messageTypeCreateShard:
return &CreateShardMessage{}
case messageTypeCreateIndex:
return &CreateIndexMessage{}
case messageTypeDeleteIndex:
return &DeleteIndexMessage{}
case messageTypeCreateField:
return &CreateFieldMessage{}
case messageTypeDeleteField:
return &DeleteFieldMessage{}
case messageTypeCreateView:
return &CreateViewMessage{}
case messageTypeDeleteView:
return &DeleteViewMessage{}
case messageTypeClusterStatus:
return &ClusterStatus{}
case messageTypeNodeState:
return &NodeStateMessage{}
case messageTypeRecalculateCaches:
return &RecalculateCaches{}
case messageTypeLoadSchemaMessage:
return &LoadSchemaMessage{}
case messageTypeNodeEvent:
return &NodeEvent{}
case messageTypeNodeStatus:
return &NodeStatus{}
case messageTypeTransaction:
return &TransactionMessage{}
case messageTypeUpdateField:
return &UpdateFieldMessage{}
case messageTypeDeleteDataframe:
return &DeleteDataframeMessage{}
default:
return nil, fmt.Errorf("invalid message type: %d", typ)
panic(fmt.Sprintf("unknown message type %d", typ))
}
}
func getMessageType(m Message) byte {
switch m.(type) {
case *CreateShardMessage:
return messageTypeCreateShard
case *CreateIndexMessage:
return messageTypeCreateIndex
case *DeleteIndexMessage:
return messageTypeDeleteIndex
case *CreateFieldMessage:
return messageTypeCreateField
case *DeleteFieldMessage:
return messageTypeDeleteField
case *CreateViewMessage:
return messageTypeCreateView
case *DeleteViewMessage:
return messageTypeDeleteView
case *ClusterStatus:
return messageTypeClusterStatus
case *NodeStateMessage:
return messageTypeNodeState
case *RecalculateCaches:
return messageTypeRecalculateCaches
case *LoadSchemaMessage:
return messageTypeLoadSchemaMessage
case *NodeEvent:
return messageTypeNodeEvent
case *NodeStatus:
return messageTypeNodeStatus
case *TransactionMessage:
return messageTypeTransaction
case *UpdateFieldMessage:
return messageTypeUpdateField
case *DeleteDataframeMessage:
return messageTypeDeleteDataframe
default:
panic(fmt.Sprintf("don't have type for message %#v", m))
}
if err := proto.Unmarshal(buf, m); err != nil {
return nil, err
}
return m, nil
}

View file

@ -1,105 +0,0 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pilosa_test
import (
"reflect"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/pilosa/pilosa"
"github.com/pilosa/pilosa/internal"
)
// Ensure a message can be marshaled and unmarshaled.
func TestMessage_Marshal(t *testing.T) {
testMessageMarshal(t, &internal.CreateSliceMessage{
Index: "i",
Slice: 8,
})
testMessageMarshal(t, &internal.DeleteIndexMessage{
Index: "i",
})
}
func testMessageMarshal(t *testing.T, m proto.Message) {
marshalled, err := pilosa.MarshalMessage(m)
if err != nil {
t.Fatal(err)
}
unmarshalled, err := pilosa.UnmarshalMessage(marshalled)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(unmarshalled, m) {
t.Fatalf("unexpected message marshalling: %s", unmarshalled)
}
}
// Ensure that BroadcastReceiver can register a BroadcastHandler.
func TestBroadcast_BroadcastReceiver(t *testing.T) {
s := pilosa.NewServer()
sbr := NewSimpleBroadcastReceiver()
sbh := NewSimpleBroadcastHandler()
s.BroadcastReceiver = sbr
s.BroadcastReceiver.Start(sbh)
msg := &internal.DeleteIndexMessage{
Index: "i",
}
s.BroadcastReceiver.(*SimpleBroadcastReceiver).Receive(msg)
// Make sure the message received is what was sentd
if !reflect.DeepEqual(sbh.receivedMessage, msg) {
t.Fatalf("unexpected message: %s", sbh.receivedMessage)
}
}
type SimpleBroadcastReceiver struct {
broadcastHandler pilosa.BroadcastHandler
}
func NewSimpleBroadcastReceiver() *SimpleBroadcastReceiver {
return &SimpleBroadcastReceiver{}
}
func (r *SimpleBroadcastReceiver) Start(h pilosa.BroadcastHandler) error {
r.broadcastHandler = h
return nil
}
func (r *SimpleBroadcastReceiver) Receive(pb proto.Message) error {
r.broadcastHandler.ReceiveMessage(pb)
return nil
}
type SimpleBroadcastHandler struct {
receivedMessage proto.Message
}
func NewSimpleBroadcastHandler() *SimpleBroadcastHandler {
return &SimpleBroadcastHandler{}
}
func (h *SimpleBroadcastHandler) ReceiveMessage(pb proto.Message) error {
h.receivedMessage = pb.(proto.Message)
return nil
}

284
bsi.go Normal file
View file

@ -0,0 +1,284 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"math/bits"
"github.com/featurebasedb/featurebase/v3/roaring"
)
// BSIData contains BSI-structured data.
type BSIData []*Row
// PivotDescending loops over nonzero BSI values in descending order.
// For each value, the provided function is called with the value and a slice of the associated columns.
// If limit or offset are not-nil, they will be applied.
// Applying a limit or offset may modify the pointed-to value.
func (bsi BSIData) PivotDescending(filter *Row, branch uint64, limit, offset *uint64, fn func(uint64, ...uint64)) {
// This "pivot" algorithm works by treating the BSI data as a tree.
// Each branch of this tree corresponds to a power-of-2-sized range of BSI values.
// Each range is subdivided into 2 ranges of half size, which form lower branches.
// Eventually, a range of width 1 cannot be subdivided and forms a leaf.
// At each branch and leaf, there is a bitmap of all columns within the corresponding range.
// The lower branches are formed as a difference or intersect of the upper branch's bitmap with the BSI bit that subdivides the range.
// This function uses a depth-first search over this virtual tree.
switch {
case !filter.Any():
// There are no remaining data.
case offset != nil && *offset >= filter.Count():
// Skip this entire branch.
*offset -= filter.Count()
case limit != nil && *limit == 0:
// The limit has been reached.
// No more data is necessary.
case len(bsi) == 0:
// This is a leaf node.
cols := filter.Columns()
if offset != nil {
cols = cols[*offset:]
*offset = 0
}
if limit != nil {
if *limit < uint64(len(cols)) {
cols = cols[:*limit]
}
*limit -= uint64(len(cols))
}
fn(branch, cols...)
default:
// Pivot over the highest bit.
upperBranch, lowerBranch := branch|(1<<uint(len(bsi)-1)), branch
splitBit := bsi[len(bsi)-1]
lowerBits := bsi[:len(bsi)-1]
lowerBits.PivotDescending(filter.Intersect(splitBit), upperBranch, limit, offset, fn)
lowerBits.PivotDescending(filter.Difference(splitBit), lowerBranch, limit, offset, fn)
}
}
/*
// distribution generates a BSI histogram for the input.
// TODO: I forgot what I was going to use this for.
// Could probbably use this for:
// - quartile queries
// - TopN on int
func (bsi bsiData) distribution(filter *Row) bsiData {
var dist bsiData
bsi.PivotDescending(filter, 0, nil, nil, func(count uint64, values ...uint64) {
dist.insert(count, uint64(len(values)))
})
return dist
}
*/
var placeholderBitmap = roaring.NewBitmap()
// AddBSI adds two BSI bitmaps together.
// It does not handle sign and has no concept of overflow.
func AddBSI(x, y BSIData) BSIData {
// Accumulate row segments.
segments := make([][]RowSegment, len(x)+len(y))
xsegs, ysegs := segments[:len(x)], segments[len(x):]
for i, r := range x {
xsegs[i] = r.Segments
}
for i, r := range y {
ysegs[i] = r.Segments
}
var dst BSIData
var xbitmaps, ybitmaps []*roaring.Bitmap
for {
// Find the next shard.
next := ^uint64(0)
for _, s := range segments {
if len(s) == 0 {
continue
}
shard := s[0].shard
if shard < next {
next = shard
}
}
if next == ^uint64(0) {
// There are no remaining shards.
break
}
// Accumulate bitmaps for this shard.
xbitmaps, ybitmaps = xbitmaps[:0], ybitmaps[:0]
for i, segs := range xsegs {
if len(segs) == 0 || segs[0].shard != next {
continue
}
xsegs[i] = segs[1:]
bm := segs[0].data
if !bm.Any() {
continue
}
for len(xbitmaps) < i {
xbitmaps = append(xbitmaps, placeholderBitmap)
}
xbitmaps = append(xbitmaps, bm)
}
for i, segs := range ysegs {
if len(segs) == 0 || segs[0].shard != next {
continue
}
ysegs[i] = segs[1:]
bm := segs[0].data
if !bm.Any() {
continue
}
for len(ybitmaps) < i {
ybitmaps = append(ybitmaps, placeholderBitmap)
}
ybitmaps = append(ybitmaps, bm)
}
// Add the shard values together.
var out []*roaring.Bitmap
switch {
case len(xbitmaps) == 0:
// There are no values in x.
out = ybitmaps
case len(ybitmaps) == 0:
// There are no values in y.
out = xbitmaps
default:
out = roaring.Add(xbitmaps, ybitmaps)
}
// Convert the bitmaps to output segments.
for i, b := range out {
if !b.Any() {
continue
}
for len(dst) <= i {
dst = append(dst, NewRow())
}
dst[i].Segments = append(dst[i].Segments, RowSegment{
shard: next,
writable: true,
data: b,
n: b.Count(),
})
}
}
return dst
}
// rowBuilder builds a row quickly from individual values.
// It is optimized for the case in which values are generated sequentially.
type rowBuilder struct {
bm *roaring.Bitmap
mask *[1024]uint64
array []uint16
key uint64
n int32
}
// flushKey flushes the data at the current key to the bitmap.
func (b *rowBuilder) flushKey() {
var c *roaring.Container
switch {
case b.mask != nil:
c = roaring.NewContainerBitmapN(b.mask[:], b.n)
b.mask = nil
case len(b.array) > 0:
c = roaring.NewContainerArrayCopy(b.array)
b.array = b.array[:0]
default:
return
}
if b.bm == nil {
b.bm = roaring.NewBitmap()
}
if old := b.bm.Containers.Get(b.key); old != nil {
c = roaring.Union(c, old)
}
b.bm.Containers.Put(b.key, c)
}
// Add a value to the bitmap.
// Values must be added sequentially.
func (b *rowBuilder) Add(v uint64) {
vkey := v / (1 << 16)
if b.key != vkey {
// This is a new key, so flush the old one.
b.flushKey()
b.key = vkey
}
if b.mask != nil {
// Add to the mask.
b.n += int32(1 &^ (b.mask[uint16(v)/64] >> (v % 64)))
b.mask[uint16(v)/64] |= 1 << (v % 64)
return
}
// Add to an array.
b.array = append(b.array, uint16(v))
if len(b.array) >= roaring.ArrayMaxSize {
// The array is too big.
// Convert it to a bitmask.
m := [1024]uint64{}
for _, v := range b.array {
m[v/64] |= 1 << (v % 64)
}
b.n = int32(len(b.array))
b.array = b.array[:0]
b.mask = &m
}
}
// Build a Row from stored data.
// This resets the builder.
func (b *rowBuilder) Build() *Row {
// Flush the active key to the bitmap.
b.flushKey()
// Remove the bitmap and convert it to a Row.
bm := b.bm
b.bm = nil
if bm == nil {
return NewRow()
}
return NewRowFromBitmap(bm)
}
// bsiBuilder assembles BSI data.
// It is optimized for the case in which values are generated sequentially.
type bsiBuilder []rowBuilder
// Insert a value into the BSI data.
// Columns must be inserted sequentially, and duplicates are not allowed.
func (b *bsiBuilder) Insert(col, val uint64) {
for val != 0 {
i := bits.TrailingZeros64(val)
val &^= 1 << i
for len(*b) <= i {
*b = append(*b, rowBuilder{})
}
(*b)[i].Add(col)
}
}
// Build BSI data.
// This resets the builder.
func (b *bsiBuilder) Build() BSIData {
builders := *b
*b = builders[:0]
rows := make(BSIData, len(builders))
for i := range builders {
rows[i] = builders[i].Build()
}
return rows
}

160
bsi_test.go Normal file
View file

@ -0,0 +1,160 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"fmt"
"math/rand"
"sort"
"testing"
)
// TestBSIAdd does a number of iterations. For each iteration, it
// generates a random number of ids, and two random values for each id
// to add together.
func TestBSIAdd(t *testing.T) {
// TODO wouldn't it be cool if our test suite had a randomized
// burn-in mode where you could run any test which supported it
// with a random seed and way more iterations?
rnd := rand.New(rand.NewSource(99))
//numZipf := rand.NewZipf(rnd, 1.5, 2, ShardWidth-1)
idZipf := rand.NewZipf(rnd, 1.8, 4, ShardWidth)
var builderA, builderB bsiBuilder
// a and b are generated slices of numbers to add together
var a, b []uint64
// idToIndex maps record ids to indexes in a and b
idToIndex := make(map[int]int)
// indexToID has the record id for each value in a and b
indexToID := []uint64{}
min := 999999999
max := 0
for iteration := 0; iteration < 1; iteration++ {
t.Run(fmt.Sprintf("%d", iteration), func(t *testing.T) {
// reset generated data
a, b = a[:0], b[:0]
indexToID = indexToID[:0]
for k := range idToIndex {
delete(idToIndex, k)
}
// z generates the values, they can be fairly large, but are usually small
z := rand.NewZipf(rnd, 1.3, 7, 1<<44)
id := -1
for i := 0; true; i++ {
// get the next id, skipping a random amount
id = id + int(idZipf.Uint64()+1)
if id >= ShardWidth {
if i < min {
min = i
}
if max < i {
max = i
}
break
}
idToIndex[id] = int(i)
indexToID = append(indexToID, uint64(id))
// append a random value to each data slice
a = append(a, z.Uint64())
b = append(b, z.Uint64())
}
// build the BSIs based on the data slices and generated IDs
for index, id := range indexToID {
va, vb := a[index], b[index]
builderA.Insert(uint64(id), va)
builderB.Insert(uint64(id), vb)
}
dataA, dataB := builderA.Build(), builderB.Build()
dataC := AddBSI(dataA, dataB)
// build results from added bsiData; results[i] should hold a[i]+b[i]
results := make([]uint64, len(a))
dataC.PivotDescending(NewRow().Union(dataC...), 0, nil, nil, func(count uint64, ids ...uint64) {
for _, id := range ids {
results[idToIndex[int(id)]] = count
}
})
for i, res := range results {
if res != a[i]+b[i] {
t.Errorf("Mismatch at %d\na: %v\nb: %v\nr: %v", i, a, b, results)
}
}
})
}
}
type bsiAddCase struct {
positions []uint64
a []uint64
b []uint64
}
func (b bsiAddCase) Len() int {
return len(b.positions)
}
// Less reports whether the element with
// index i should sort before the element with index j.
func (b bsiAddCase) Less(i, j int) bool {
return b.positions[i] < b.positions[j]
}
// Swap swaps the elements with indexes i and j.
func (b bsiAddCase) Swap(i, j int) {
b.positions[i], b.positions[j] = b.positions[j], b.positions[i]
b.a[i], b.a[j] = b.a[j], b.a[i]
b.b[i], b.b[j] = b.b[j], b.b[i]
}
// TestBSIAddCases tests specific cases of bsiAdd (would generally be
// pulled from randomly generated ones from TestBSIAdd upon failure).
func TestBSIAddCases(t *testing.T) {
tests := []bsiAddCase{
{
positions: []uint64{161311, 611110, 82544, 996022, 836077, 64964, 480737, 156534, 240525, 580896, 239236, 54607, 1019438, 894260, 17570, 884645, 936658, 682651, 987695, 390274},
a: []uint64{17, 1, 2846, 45437619, 23781, 36, 88, 168691, 13417, 1301, 10, 71, 0, 176, 1010, 21, 1, 509, 17, 4},
b: []uint64{24, 288, 12737, 14, 150, 21, 24, 354, 0, 19, 5, 150, 3940, 121, 25, 621, 7, 9023592401, 6033, 7},
},
{
positions: []uint64{17570, 54607},
a: []uint64{1010, 71},
b: []uint64{25, 150},
},
}
var builderA, builderB bsiBuilder
for i, tst := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
if len(tst.a) != len(tst.b) || len(tst.a) != len(tst.positions) {
t.Fatalf("Malformed test, a is %d, but b is %d", len(tst.a), len(tst.b))
}
sort.Sort(tst)
for i := 0; i < len(tst.a); i++ {
builderA.Insert(tst.positions[i], tst.a[i])
builderB.Insert(tst.positions[i], tst.b[i])
}
dataA, dataB := builderA.Build(), builderB.Build()
dataC := AddBSI(dataA, dataB)
// maps id to count
results := make(map[uint64]uint64)
dataC.PivotDescending(NewRow().Union(dataC...), 0, nil, nil, func(count uint64, ids ...uint64) {
for _, id := range ids {
results[id] = count
}
})
for i, id := range tst.positions {
if results[id] != tst.a[i]+tst.b[i] {
t.Fatalf("value %d mismatch, id: %d. got %d, want %d", i, id, results[id], tst.a[i]+tst.b[i])
}
}
})
}
}

110
buffer/filebuffer.go Normal file
View file

@ -0,0 +1,110 @@
package buffer
import (
"bytes"
"io"
"io/ioutil"
"os"
"sync"
)
// NewFileBuffer returns a file buffer which will use an in-memory buffer, until `max` bytes have been written, at which point it will write the contents of memory to a file, and continue writing future data to the file.
// The file will be written to `temp` directory. The buffer fulfills the io.Reader and io.Writer interface
func NewFileBuffer(max int, temp string) *FileBuffer {
return &FileBuffer{max: max, tempDir: temp}
}
type FileBuffer struct {
max int
buf bytes.Buffer
file *os.File
tempDir string
reading bool
files []*os.File
mu sync.Mutex
}
func (fb *FileBuffer) Write(p []byte) (n int, err error) {
if fb.reading {
panic("cannot write after read")
}
if fb.file != nil {
return fb.file.Write(p)
}
n, err = fb.buf.Write(p)
if err != nil {
return
}
if fb.buf.Len() > fb.max {
fb.file, err = ioutil.TempFile(fb.tempDir, "filebuffer-")
if err != nil {
return
}
_, err = io.Copy(fb.file, &fb.buf)
fb.buf.Reset()
}
return
}
func (fb *FileBuffer) Len() (int64, error) {
if fb.file == nil {
return int64(fb.buf.Len()), nil
}
fi, err := fb.file.Stat()
if err != nil {
return 0, err
}
return fi.Size(), nil
}
func (fb *FileBuffer) Read(p []byte) (n int, err error) {
if fb.file != nil {
if !fb.reading {
fb.reading = true
_, err = fb.file.Seek(0, 0)
if err != nil {
return
}
}
return fb.file.Read(p)
}
fb.reading = true
return fb.buf.Read(p)
}
func (fb *FileBuffer) Close() error {
if fb.file != nil {
name := fb.file.Name()
if err := fb.file.Close(); err != nil {
return err
}
for _, f := range fb.files {
f.Close()
}
fb.files = fb.files[:0]
fb.file = nil
return os.Remove(name)
}
return nil
}
func (fb *FileBuffer) Reset() error {
fb.mu.Lock()
defer fb.mu.Unlock()
fb.reading = false
fb.buf.Reset()
return fb.Close()
}
func (fb *FileBuffer) NewReader() (io.Reader, error) {
fb.mu.Lock()
defer fb.mu.Unlock()
fb.reading = true
if fb.file == nil {
return bytes.NewReader(fb.buf.Bytes()), nil
}
f, err := os.OpenFile(fb.file.Name(), os.O_RDONLY, 0)
fb.files = append(fb.files, f)
return f, err
}

262
bufferpool/bufferpool.go Normal file
View file

@ -0,0 +1,262 @@
package bufferpool
import (
"errors"
"fmt"
"sync"
)
// FrameID is the type for frame id
type FrameID int
// PageID is the type for page id
type PageID int
var pageSyncPool = sync.Pool{
New: func() any {
pg := new(Page)
pg.id = PageID(INVALID_PAGE)
pg.isDirty = false
pg.pinCount = 0
return pg
},
}
// BufferPool represents a buffer pool of pages
type BufferPool struct {
// the underlying storage
diskManager DiskManager
// the actual pages in the buffer pool
pages []*Page
// the replacer that will elect replacements when buffer pool is full
replacer *ClockReplacer
// the list of free frames
freeList []FrameID
// the map of frames to page ids to frame ids
// frame ids are the offset into pages
// if you ask the pool for page 673, this will know at
// what offset in pages page 673 will exist
pageTable map[PageID]FrameID
}
// TODO(pok) implement a lazy writer
// * if free list is 'low' then
// * increase size of cache if there is physical memory available
// * write out old pages and boot them from the cache to increase free list
// TODO(pok) implement a checkpoint that scans the pool and writes out dirty pages every
// minute or so
// NewBufferPool returns a buffer pool
func NewBufferPool(maxSize int, diskManager DiskManager) *BufferPool {
freeList := make([]FrameID, 0)
pages := make([]*Page, maxSize)
for i := 0; i < maxSize; i++ {
frameNumber := FrameID(i)
freeList = append(freeList, frameNumber)
}
clockReplacer := NewClockReplacer(maxSize)
return &BufferPool{
diskManager: diskManager,
pages: pages,
replacer: clockReplacer,
freeList: freeList,
pageTable: make(map[PageID]FrameID),
}
}
// Dumps all the pages in the buffer pool
func (b *BufferPool) Dump() {
fmt.Println()
fmt.Printf("------------------------------------------------------------------------------------------\n")
fmt.Printf("BUFFER POOL\n")
for _, p := range b.pages {
if p != nil {
p.Dump("")
}
}
fmt.Printf("------------------------------------------------------------------------------------------\n")
fmt.Println()
}
// FetchPage fetches the requested page from the buffer pool.
func (b *BufferPool) FetchPage(pageID PageID) (*Page, error) {
// if it is in buffer pool already then just return it
if frameID, ok := b.pageTable[pageID]; ok {
page := b.pages[frameID]
page.pinCount++
b.replacer.Pin(frameID)
return page, nil
}
// not in the buffer pool so try the free list or
// the replacer will vote a page off the island
frameID, isFromFreeList, err := b.getFrameID()
if err != nil {
return nil, err
}
if !isFromFreeList {
// if it didn't come from the freelist then
// remove page from current frame, writing it out if dirty
currentPage := b.pages[frameID]
if currentPage != nil {
if currentPage.isDirty {
b.diskManager.WritePage(currentPage)
}
delete(b.pageTable, currentPage.id)
}
}
// if we got to here, sorry, have to do an I/O
page, err := b.diskManager.ReadPage(pageID)
if err != nil {
return nil, err
}
page.pinCount = 1
b.pageTable[pageID] = frameID
pageSyncPool.Put(b.pages[frameID])
b.pages[frameID] = page
b.replacer.Pin(frameID)
return page, nil
}
// UnpinPage unpins the target page from the buffer pool
func (b *BufferPool) UnpinPage(pageID PageID) error {
if frameID, ok := b.pageTable[pageID]; ok {
page := b.pages[frameID]
page.DecPinCount()
if page.pinCount <= 0 {
b.replacer.Unpin(frameID)
}
return nil
}
return errors.New("could not find page")
}
// FlushPage Flushes the target page to disk
func (b *BufferPool) FlushPage(pageID PageID) bool {
if frameID, ok := b.pageTable[pageID]; ok {
page := b.pages[frameID]
page.DecPinCount()
b.diskManager.WritePage(page)
page.isDirty = false
return true
}
return false
}
// NewPage allocates a new page in the buffer pool with the disk manager help
func (b *BufferPool) NewPage() (*Page, error) {
// get a free frame
frameID, isFromFreeList, err := b.getFrameID()
if err != nil {
return nil, err
}
if !isFromFreeList {
// remove page from current frame
currentPage := b.pages[frameID]
if currentPage != nil {
if currentPage.isDirty {
b.diskManager.WritePage(currentPage)
}
delete(b.pageTable, currentPage.id)
}
}
// allocates new page
pageID, err := b.diskManager.AllocatePage()
if err != nil {
return nil, err
}
page := &Page{pageID, 1, false, [PAGE_SIZE]byte{}}
page.WritePageNumber(int32(pageID))
page.WriteFreeSpaceOffset(int16(PAGE_SIZE))
page.WriteNextPointer(int32(INVALID_PAGE))
page.WritePrevPointer(int32(INVALID_PAGE))
// update the frame table
b.pageTable[pageID] = frameID
pageSyncPool.Put(b.pages[frameID])
b.pages[frameID] = page
return page, nil
}
// ScratchPage returns a page outside the buffer pool - do not use if you intend the page
// to be in the buffer pool (use NewPage() for that)
// ScratchPage is intended to be used in cases where you need the Page primitives
// and will copy the scratch page back over a real page later
func (b *BufferPool) ScratchPage() *Page {
page := &Page{
id: PageID(INVALID_PAGE),
pinCount: 0,
isDirty: false,
data: [PAGE_SIZE]byte{},
}
page.WritePageNumber(int32(INVALID_PAGE))
page.WriteFreeSpaceOffset(int16(PAGE_SIZE))
page.WriteNextPointer(int32(INVALID_PAGE))
page.WritePrevPointer(int32(INVALID_PAGE))
return page
}
// DeletePage deletes a page from the buffer pool
func (b *BufferPool) DeletePage(pageID PageID) error {
var frameID FrameID
var ok bool
if frameID, ok = b.pageTable[pageID]; !ok {
return nil
}
page := b.pages[frameID]
if page.pinCount > 0 {
return errors.New("pin count greater than 0")
}
delete(b.pageTable, page.id)
b.replacer.Pin(frameID)
b.diskManager.DeallocatePage(pageID)
b.freeList = append(b.freeList, frameID)
return nil
}
// FlushAllpages flushes all the pages in the buffer pool to disk
// Yeah, never call this unless you know what you are doing
func (b *BufferPool) FlushAllpages() {
for pageID := range b.pageTable {
b.FlushPage(pageID)
}
}
func (b *BufferPool) getFrameID() (FrameID, bool, error) {
if len(b.freeList) > 0 {
frameID, newFreeList := b.freeList[0], b.freeList[1:]
b.freeList = newFreeList
return frameID, true, nil
}
victim, err := b.replacer.Victim()
return victim, false, err
}
// OnDiskSize exposes the on disk size of the backing store
// behind this buffer pool
func (b *BufferPool) OnDiskSize() int64 {
return b.diskManager.FileSize()
}
// Close closes the buffer pool
func (b *BufferPool) Close() {
b.diskManager.Close()
}

View file

@ -0,0 +1,93 @@
package bufferpool
import (
"errors"
)
type circularListNode struct {
key interface{}
value interface{}
next *circularListNode
prev *circularListNode
}
type circularList struct {
head *circularListNode
tail *circularListNode
size int
capacity int
}
func newCircularList(maxSize int) *circularList {
return &circularList{nil, nil, 0, maxSize}
}
func (c *circularList) find(key interface{}) *circularListNode {
ptr := c.head
for i := 0; i < c.size; i++ {
if ptr.key == key {
return ptr
}
ptr = ptr.next
}
return nil
}
func (c *circularList) hasKey(key interface{}) bool {
return c.find(key) != nil
}
func (c *circularList) insert(key interface{}, value interface{}) error {
if c.size == c.capacity {
return errors.New("list is full")
}
newNode := &circularListNode{key, value, nil, nil}
if c.size == 0 {
newNode.next = newNode
newNode.prev = newNode
c.head = newNode
c.tail = newNode
c.size++
return nil
}
node := c.find(key)
if node != nil {
node.value = value
return nil
}
newNode.next = c.head
newNode.prev = c.tail
c.tail.next = newNode
if c.head == c.tail {
c.head.next = newNode
}
c.tail = newNode
c.head.prev = c.tail
c.size++
return nil
}
func (c *circularList) remove(key interface{}) {
node := c.find(key)
if node == nil {
return
}
if c.size == 1 {
c.head = nil
c.tail = nil
c.size--
return
}
if node == c.head {
c.head = c.head.next
}
if node == c.tail {
c.tail = c.tail.prev
}
node.next.prev = node.prev
node.prev.next = node.next
c.size--
}

View file

@ -0,0 +1,64 @@
package bufferpool
import "errors"
// ClockReplacer implements a clock replacer algorithm
type ClockReplacer struct {
cList *circularList
clockHand **circularListNode
}
// NewClockReplacer instantiates a new clock replacer
func NewClockReplacer(poolSize int) *ClockReplacer {
cList := newCircularList(poolSize)
return &ClockReplacer{cList, &cList.head}
}
// Victim removes the victim frame as defined by the replacement policy
func (c *ClockReplacer) Victim() (FrameID, error) {
if c.cList.size == 0 {
return FrameID(INVALID_PAGE), errors.New("no victims available")
}
var victimFrameID FrameID
currentNode := (*c.clockHand)
for {
if currentNode.value.(bool) {
currentNode.value = false
c.clockHand = &currentNode.next
} else {
frameID := currentNode.key.(FrameID)
victimFrameID = frameID
c.clockHand = &currentNode.next
c.cList.remove(currentNode.key)
return victimFrameID, nil
}
}
}
// Unpin unpins a frame, indicating that it can now be victimized
func (c *ClockReplacer) Unpin(id FrameID) {
if !c.cList.hasKey(id) {
c.cList.insert(id, true)
if c.cList.size == 1 {
c.clockHand = &c.cList.head
}
}
}
// Pin pins a frame, indicating that it should not be victimized until it is unpinned
func (c *ClockReplacer) Pin(id FrameID) {
node := c.cList.find(id)
if node == nil {
return
}
if (*c.clockHand) == node {
c.clockHand = &(*c.clockHand).next
}
c.cList.remove(id)
}
// Size returns the size of the clock
func (c *ClockReplacer) Size() int {
return c.cList.size
}

21
bufferpool/diskmanager.go Normal file
View file

@ -0,0 +1,21 @@
package bufferpool
// DiskManager is responsible for interacting with disk
type DiskManager interface {
// reads a page from the disk
ReadPage(PageID) (*Page, error)
// writes a page to the disk
WritePage(*Page) error
// allocates a page
AllocatePage() (PageID, error)
// deallocates a page
DeallocatePage(PageID) error
// returns on disk file size
FileSize() int64
// closes and does any clean up
Close()
}

View file

@ -0,0 +1,162 @@
package bufferpool
import (
"errors"
"fmt"
"os"
uuid "github.com/satori/go.uuid"
)
// InMemDiskSpillingDiskManager is a memory implementation for a DiskManager interface
// that can spill to disk when a threshold is reached
type InMemDiskSpillingDiskManager struct {
// tracks the number of pages
numPages int
onDiskPages int
// tracks the number of pages we can consume before spilling
thresholdPages int
hasSpilled *struct{}
fd *os.File
// the data buffer
data []byte
}
// NewInMemDiskSpillingDiskManager returns a in-memory version of disk manager
func NewInMemDiskSpillingDiskManager(thresholdPages int) *InMemDiskSpillingDiskManager {
dm := &InMemDiskSpillingDiskManager{
numPages: 0,
thresholdPages: thresholdPages,
data: make([]byte, 0),
}
return dm
}
// ReadPage reads a page from pages
func (d *InMemDiskSpillingDiskManager) ReadPage(pageID PageID) (*Page, error) {
// check we're not asking for page out of range
if pageID < 0 || int(pageID) >= d.numPages {
return nil, errors.New("page not found")
}
// check that the offset is within range
offset := int(pageID) * PAGE_SIZE
var page = pageSyncPool.Get().(*Page)
// we have to do this stupid check because if -cpuprofile is set for go test, this
// the previous line return a weird nil-ish thing...
if page == (*Page)(nil) {
page = pageSyncPool.New().(*Page)
}
page.id = pageID
// do the read
if d.hasSpilled == nil {
if offset+PAGE_SIZE > len(d.data) {
return nil, errors.New("offset out of range")
}
b := copy(page.data[:], d.data[offset:offset+PAGE_SIZE])
fmt.Printf("bytes read: %d", b)
} else {
var err error
if offset+PAGE_SIZE > d.numPages*PAGE_SIZE {
return nil, errors.New("offset out of range")
}
_, err = d.fd.ReadAt(page.data[:], int64(offset))
if err != nil {
return nil, err
}
}
return page, nil
}
// WritePage writes a page in memory to pages
func (d *InMemDiskSpillingDiskManager) WritePage(page *Page) error {
// make sure the offset is sensible
offset := int(page.ID()) * PAGE_SIZE
// do the write
if d.hasSpilled == nil {
if offset+PAGE_SIZE > len(d.data) {
return errors.New("offset out of range")
}
copy(d.data[offset:], page.data[:])
} else {
var err error
if offset+PAGE_SIZE > d.numPages*PAGE_SIZE {
return errors.New("offset out of range")
}
_, err = d.fd.WriteAt(page.data[:], int64(offset))
if err != nil {
return err
}
// err = d.fd.Sync()
// if err != nil {
// return err
// }
}
return nil
}
// AllocatePage allocates a page and returns the page number
func (d *InMemDiskSpillingDiskManager) AllocatePage() (PageID, error) {
d.numPages = d.numPages + 1
pageID := PageID(d.numPages - 1)
if d.hasSpilled == nil {
// we have not spilled (yet), so make storage bigger
newData := make([]byte, PAGE_SIZE)
d.data = append(d.data, newData...)
// check to see if we need to spill
if d.numPages > d.thresholdPages {
fileUUID, err := uuid.NewV4()
if err != nil {
return PageID(INVALID_PAGE), err
}
// TODO(pok) we should try to tell the OS not to cache this file
d.fd, err = os.CreateTemp("", fmt.Sprintf("fb-ehash-%s", fileUUID.String()))
if err != nil {
return PageID(INVALID_PAGE), err
}
_, err = d.fd.WriteAt(d.data, 0)
if err != nil {
return PageID(INVALID_PAGE), err
}
d.data = []byte{}
d.hasSpilled = &struct{}{}
}
} else {
if d.numPages >= d.onDiskPages {
// grow the file by a chunk - 512 pages
d.onDiskPages += 512
var err error
size := int64(d.onDiskPages * PAGE_SIZE)
_, err = d.fd.WriteAt([]byte{0}, size-1)
if err != nil {
return PageID(INVALID_PAGE), err
}
}
}
return pageID, nil
}
// DeallocatePage removes page from disk
func (d *InMemDiskSpillingDiskManager) DeallocatePage(pageID PageID) error {
// nothing to do right now
return nil
}
func (d *InMemDiskSpillingDiskManager) FileSize() int64 {
return int64(len(d.data))
}
func (d *InMemDiskSpillingDiskManager) Close() {
// close and delete the file if we spilled
if d.fd != nil {
_ = d.fd.Close()
os.Remove(d.fd.Name())
}
}

371
bufferpool/page.go Normal file
View file

@ -0,0 +1,371 @@
package bufferpool
import (
"encoding/binary"
"errors"
"fmt"
)
const PAGE_SIZE int = 8192
const INVALID_PAGE int = -1
const PAGE_TYPE_BTREE_INTERNAL = 10
const PAGE_TYPE_BTREE_LEAF = 11
const PAGE_TYPE_HASH_TABLE = 12
// PAGE
// page size 8192 bytes
// byte aligned, big endian
// |====================================================|
// | offset | length | |
// |----------------------------------------------------|
// | header |
// |====================================================|
// | 0 | 4 | pageNumber (int32) |
// | 4 | 2 | pageType (int16) |
// | 6 | 2 | slotCount (int16) |
// | 8 | 2 | localDepth (int16) |
// | 10 | 2 | freeSpaceOffset (int16) |
// | 12 | 4 | prevPointer (int32) |
// | 16 | 4 | nextPointer (int32) |
// |====================================================|
// | <start of slot array 1..slotCount> |
// |----------------------------------------------------|
// | 20 | slotcount | slot entry is 2 int16 |
// | | * slotwidth | values (payloadOffset, |
// | | * #slots | payloadLength) |
// |----------------------------------------------------|
// | <free space> |
// |----------------------------------------------------|
// | <payload starting at freeSpaceOffset> |
// | payload entries are keylength (int16), key bytes, |
// | payload length (int32), payload bytes |
// |====================================================|
const PAGE_NUMBER_OFFSET = 0 // offset 0, length 4, end 4
const PAGE_TYPE_OFFSET = 4 // offset 4, length 2, end 6
const PAGE_SLOT_COUNT_OFFSET = 6 // offset 6, length 2, end 8
const PAGE_LOCAL_DEPTH_OFFSET = 8 // offset 8, length 2, end 10
const PAGE_FREE_SPACE_OFFSET = 10 // offset 10, length 2, end 12
const PAGE_PREV_POINTER_OFFSET = 12 // offset 12, length 4, end 16
const PAGE_NEXT_POINTER_OFFSET = 16 // offset 16, length 4, end 20
const PAGE_SLOTS_START_OFFSET = 20 // offset 20
// PAGE_SLOT_LENGTH is the size of the page slot key/value.
//
// key offset int16 //offset 0, length 2, end 2
// value offset int16 //offset 2, length 2, end 4
const PAGE_SLOT_LENGTH = 4
// Page represents a page on disk
type Page struct {
id PageID
pinCount int
isDirty bool
data [PAGE_SIZE]byte
}
type PageSlot struct {
KeyOffset int16
ValueOffset int16
}
func (s *PageSlot) KeyBytes(page *Page) []byte {
offset := s.KeyOffset
keyLen := int16(binary.BigEndian.Uint16(page.data[offset:]))
offset += 2
result := make([]byte, keyLen)
copy(result, page.data[offset:offset+keyLen])
return result
}
func (s *PageSlot) KeyAsInt(page *Page) int32 {
return int32(binary.BigEndian.Uint32(page.data[s.KeyOffset+2:]))
}
func (s *PageSlot) ValueBytes(page *Page) []byte {
offset := s.ValueOffset
valueLen := int32(binary.BigEndian.Uint32(page.data[offset:]))
offset += 4
result := make([]byte, valueLen)
copy(result, page.data[offset:int32(offset)+valueLen])
return result
}
func (s *PageSlot) ValueAsPagePointer(page *Page) int32 {
return int32(binary.BigEndian.Uint32(page.data[s.ValueOffset+4:]))
}
type PageChunk struct {
KeyLength int16
KeyBytes []byte
// TODO(pok) ValueBytes can be up to int32 long
// this requires an overflow page mechanism, that is not implemented
// yet, so be aware of this when storing stuff...
ValueLength int32
ValueBytes []byte
}
func (pc *PageChunk) Length() int {
return 2 + len(pc.KeyBytes) + 4 + len(pc.ValueBytes)
}
func (pc *PageChunk) ComputeKeyOffset(pageOffset int) int {
return pageOffset
}
func (pc *PageChunk) ComputeValueOffset(pageOffset int) int {
return pageOffset + 2 + len(pc.KeyBytes)
}
func (p *Page) WritePageNumber(pageNumber int32) {
p.id = PageID(pageNumber)
binary.BigEndian.PutUint32(p.data[PAGE_NUMBER_OFFSET:], uint32(pageNumber))
p.isDirty = true
}
func (p *Page) ReadPageNumber() int {
return int(binary.BigEndian.Uint32(p.data[PAGE_NUMBER_OFFSET:]))
}
func (p *Page) WritePageType(pageType int16) {
binary.BigEndian.PutUint16(p.data[PAGE_TYPE_OFFSET:], uint16(pageType))
p.isDirty = true
}
func (p *Page) ReadPageType() int16 {
return int16(binary.BigEndian.Uint16(p.data[PAGE_TYPE_OFFSET:]))
}
func (p *Page) WriteSlotCount(slotCount int16) {
binary.BigEndian.PutUint16(p.data[PAGE_SLOT_COUNT_OFFSET:], uint16(slotCount))
p.isDirty = true
}
func (p *Page) ReadSlotCount() int16 {
return int16(binary.BigEndian.Uint16(p.data[PAGE_SLOT_COUNT_OFFSET:]))
}
func (p *Page) WriteLocalDepth(localDepth int16) {
binary.BigEndian.PutUint16(p.data[PAGE_LOCAL_DEPTH_OFFSET:], uint16(localDepth))
p.isDirty = true
}
func (p *Page) ReadLocalDepth() int16 {
return int16(binary.BigEndian.Uint16(p.data[PAGE_LOCAL_DEPTH_OFFSET:]))
}
func (p *Page) ReadSlot(slot int16) PageSlot {
offset := PAGE_SLOTS_START_OFFSET + PAGE_SLOT_LENGTH*slot
keyOffset := int16(binary.BigEndian.Uint16(p.data[offset:]))
offset += 2
valueOffset := int16(binary.BigEndian.Uint16(p.data[offset:]))
return PageSlot{
KeyOffset: keyOffset,
ValueOffset: valueOffset,
}
}
func (p *Page) WriteSlot(slot int16, value PageSlot) {
offset := PAGE_SLOTS_START_OFFSET + PAGE_SLOT_LENGTH*slot
binary.BigEndian.PutUint16(p.data[offset:], uint16(value.KeyOffset))
offset += 2
binary.BigEndian.PutUint16(p.data[offset:], uint16(value.ValueOffset))
}
func (p *Page) WriteFreeSpaceOffset(offset int16) {
binary.BigEndian.PutUint16(p.data[PAGE_FREE_SPACE_OFFSET:], uint16(offset))
p.isDirty = true
}
func (p *Page) ReadFreeSpaceOffset() int16 {
return int16(binary.BigEndian.Uint16(p.data[PAGE_FREE_SPACE_OFFSET:]))
}
func (p *Page) WritePrevPointer(prevPointer int32) {
binary.BigEndian.PutUint32(p.data[PAGE_PREV_POINTER_OFFSET:], uint32(prevPointer))
p.isDirty = true
}
func (p *Page) ReadPrevPointer() int {
return int(binary.BigEndian.Uint32(p.data[PAGE_PREV_POINTER_OFFSET:]))
}
func (p *Page) WriteNextPointer(nextPointer int32) {
binary.BigEndian.PutUint32(p.data[PAGE_NEXT_POINTER_OFFSET:], uint32(nextPointer))
p.isDirty = true
}
func (p *Page) ReadNextPointer() int {
return int(binary.BigEndian.Uint32(p.data[PAGE_NEXT_POINTER_OFFSET:]))
}
func (p *Page) WriteChunk(offset int16, chunk PageChunk) {
binary.BigEndian.PutUint16(p.data[offset:], uint16(chunk.KeyLength))
offset += 2
copy(p.data[offset:], chunk.KeyBytes)
offset += int16(len(chunk.KeyBytes))
binary.BigEndian.PutUint32(p.data[offset:], uint32(chunk.ValueLength))
offset += 4
copy(p.data[offset:], chunk.ValueBytes)
p.isDirty = true
}
func (p *Page) ReadChunk(offset int16) PageChunk {
keyLen := int16(binary.BigEndian.Uint16(p.data[offset:]))
offset += 2
keyBytes := make([]byte, keyLen)
copy(keyBytes, p.data[offset:offset+keyLen])
offset += keyLen
valueLen := int32(binary.BigEndian.Uint32(p.data[offset:]))
offset += 4
valueBytes := make([]byte, valueLen)
copy(valueBytes, p.data[offset:int32(offset)+valueLen])
return PageChunk{
KeyLength: keyLen,
KeyBytes: keyBytes,
ValueLength: valueLen,
ValueBytes: valueBytes,
}
}
func (p *Page) FreeSpace() int16 {
freeSpaceOffset := p.ReadFreeSpaceOffset()
freespace := freeSpaceOffset - (p.ReadSlotCount()*PAGE_SLOT_LENGTH + PAGE_SLOT_LENGTH + PAGE_SLOTS_START_OFFSET)
return freespace
}
func (p *Page) WriteKeyValueInSlot(slotNumber int16, key []byte, value []byte) error {
freeSpaceOffset := p.ReadFreeSpaceOffset()
// build a chunk
chunk := PageChunk{
KeyLength: int16(len(key)),
KeyBytes: key,
ValueLength: int32(len(value)),
ValueBytes: value,
}
// compute the new free space offset
freeSpaceOffset -= int16(chunk.Length())
// check we won't blow free space on page
slotCount := p.ReadSlotCount()
slotEndOffset := slotCount*PAGE_SLOT_LENGTH + PAGE_SLOT_LENGTH + PAGE_SLOTS_START_OFFSET
// DEBUG!!
//fmt.Printf("freeSpaceOffset: %d, slotCount: %d, slotCount*4 + 4 + 20: %d, freeSpace: %d\n", freeSpaceOffset, slotCount, slotEndOffset, freeSpaceOffset-slotEndOffset)
if freeSpaceOffset-slotEndOffset <= 0 {
return errors.New("page is full")
}
keyOffset := chunk.ComputeKeyOffset(int(freeSpaceOffset))
valueOffset := chunk.ComputeValueOffset(int(freeSpaceOffset))
p.WriteChunk(freeSpaceOffset, chunk)
// update the free space offset
p.WriteFreeSpaceOffset(int16(freeSpaceOffset))
// make a slot
slot := PageSlot{
KeyOffset: int16(keyOffset),
ValueOffset: int16(valueOffset),
}
// write the slot
p.WriteSlot(slotNumber, slot)
return nil
}
func (p *Page) WritePage(page *Page) {
// copy everything but pageNumber & pageType
offset := PAGE_SLOT_COUNT_OFFSET
copy(page.data[offset:], p.data[offset:offset+PAGE_SIZE-offset])
}
func (p *Page) PinCount() int {
return p.pinCount
}
func (p *Page) ID() PageID {
return p.id
}
func (p *Page) DecPinCount() {
if p.pinCount > 0 {
p.pinCount--
}
}
type PageSlotIterator struct {
page *Page
slotCount int16
cursor int16
}
func NewPageSlotIterator(page *Page, fromSlot int16) *PageSlotIterator {
i := &PageSlotIterator{
page: page,
slotCount: page.ReadSlotCount(),
cursor: fromSlot,
}
return i
}
func (i *PageSlotIterator) Next() *PageSlot {
if i.cursor < i.slotCount {
s := i.page.ReadSlot(i.cursor)
i.cursor++
return &s
}
return nil
}
func (i *PageSlotIterator) Cursor() int16 {
return i.cursor
}
func (pg *Page) Dump(label string) {
indent := 0
if len(label) > 0 {
fmt.Printf("%s%s:\n", fmt.Sprintf("%*s", indent, ""), label)
indent += 4
}
pageType := pg.ReadPageType()
fmt.Printf("%sPAGE(%d) pageType: %d slotCount: %d, prevPtr: %d, nextPtr: %d\n", fmt.Sprintf("%*s", indent, ""), pg.ID(), pageType, pg.ReadSlotCount(), pg.ReadPrevPointer(), pg.ReadNextPointer())
fmt.Printf("%sKEYS: -->\n", fmt.Sprintf("%*s", indent, ""))
indent += 4
// get the keys off the page
keys := make([]int, 0)
pointers := make([]int, 0)
iter := NewPageSlotIterator(pg, 0)
for {
ps := iter.Next()
if ps == nil {
break
}
keys = append(keys, int(ps.KeyAsInt(pg)))
if pageType == /*nodeTypeInternal*/ 10 {
pointers = append(pointers, int(ps.ValueAsPagePointer(pg)))
}
}
if pageType == /*nodeTypeLeaf*/ 11 {
for _, key := range keys {
fmt.Printf("%s(%d)\n", fmt.Sprintf("%*s", indent, ""), key)
}
} else {
for idx, key := range keys {
ptr := pointers[idx]
fmt.Printf("%s(%d, %d)\n", fmt.Sprintf("%*s", indent, ""), key, ptr)
}
ptr := pg.ReadNextPointer()
fmt.Printf("%s(-->, %d)\n", fmt.Sprintf("%*s", indent, ""), ptr)
}
}

501
cache.go
View file

@ -1,38 +1,28 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"bytes"
"encoding/json"
"fmt"
"io"
"sort"
"sync"
"time"
"github.com/golang/groupcache/lru"
"github.com/pilosa/pilosa/internal"
"github.com/featurebasedb/featurebase/v3/lru"
pb "github.com/featurebasedb/featurebase/v3/proto"
"github.com/pkg/errors"
)
const (
// ThresholdFactor is used to calculate the threshold for new items entering the cache
ThresholdFactor = 1.1
// thresholdFactor is used to calculate the threshold for new items entering the cache
thresholdFactor = 1.1
)
// Cache represents a cache of counts.
type Cache interface {
// cache represents a cache of counts.
type cache interface {
Add(id uint64, n uint64)
BulkAdd(id uint64, n uint64)
Get(id uint64) uint64
@ -41,66 +31,67 @@ type Cache interface {
// Returns a list of all IDs.
IDs() []uint64
// Updates the cache, if necessary.
// Soft ask for the cache to be rebuilt - may not if it has been done recently.
Invalidate()
// Rebuilds the cache
// Rebuilds the cache.
Recalculate()
// Returns an ordered list of the top ranked bitmaps.
Top() []BitmapPair
Top() []bitmapPair
// SetStats defines the stats client used in the cache.
SetStats(s StatsClient)
// Clear removes everything from the cache. If possible it should leave allocated structures in place to be reused.
Clear()
}
// LRUCache represents a least recently used Cache implementation.
type LRUCache struct {
// lruCache represents a least recently used Cache implementation.
type lruCache struct {
cache *lru.Cache
counts map[uint64]uint64
stats StatsClient
// maxEntries is saved to support Clear which recreates the cache.
maxEntries uint32
}
// NewLRUCache returns a new instance of LRUCache.
func NewLRUCache(maxEntries uint32) *LRUCache {
c := &LRUCache{
cache: lru.New(int(maxEntries)),
counts: make(map[uint64]uint64),
stats: NopStatsClient,
// newLRUCache returns a new instance of LRUCache.
func newLRUCache(maxEntries uint32) *lruCache {
c := &lruCache{
cache: lru.New(int(maxEntries)),
counts: make(map[uint64]uint64),
maxEntries: maxEntries,
}
c.cache.OnEvicted = c.onEvicted
return c
}
// BulkAdd adds a count to the cache unsorted. You should Invalidate after completion.
func (c *LRUCache) BulkAdd(id, n uint64) {
func (c *lruCache) BulkAdd(id, n uint64) {
c.Add(id, n)
}
// Add adds a count to the cache.
func (c *LRUCache) Add(id, n uint64) {
func (c *lruCache) Add(id, n uint64) {
c.cache.Add(id, n)
c.counts[id] = n
}
// Get returns a count for a given id.
func (c *LRUCache) Get(id uint64) uint64 {
func (c *lruCache) Get(id uint64) uint64 {
n, _ := c.cache.Get(id)
nn, _ := n.(uint64)
return nn
}
// Len returns the number of items in the cache.
func (c *LRUCache) Len() int { return c.cache.Len() }
func (c *lruCache) Len() int { return c.cache.Len() }
// Invalidate is a no-op.
func (c *LRUCache) Invalidate() {}
func (c *lruCache) Invalidate() {}
// Recalculate is a no-op.
func (c *LRUCache) Recalculate() {}
func (c *lruCache) Recalculate() {}
// IDs returns a list of all IDs in the cache.
func (c *LRUCache) IDs() []uint64 {
func (c *lruCache) IDs() []uint64 {
a := make([]uint64, 0, len(c.counts))
for id := range c.counts {
a = append(a, id)
@ -110,33 +101,39 @@ func (c *LRUCache) IDs() []uint64 {
}
// Top returns all counts in the cache.
func (c *LRUCache) Top() []BitmapPair {
a := make([]BitmapPair, 0, len(c.counts))
func (c *lruCache) Top() []bitmapPair {
a := make([]bitmapPair, 0, len(c.counts))
for id, n := range c.counts {
a = append(a, BitmapPair{
a = append(a, bitmapPair{
ID: id,
Count: uint64(n),
Count: n,
})
}
sort.Sort(BitmapPairs(a))
pairs := bitmapPairs(a)
sort.Sort(&pairs)
return a
}
// SetStats defines the stats client used in the cache.
func (c *LRUCache) SetStats(s StatsClient) {
c.stats = s
func (c *lruCache) Clear() {
for k := range c.counts {
delete(c.counts, k)
}
c.cache = lru.New(int(c.maxEntries))
}
func (c *LRUCache) onEvicted(key lru.Key, _ interface{}) { delete(c.counts, key.(uint64)) }
func (c *lruCache) onEvicted(key lru.Key, _ interface{}) { delete(c.counts, key.(uint64)) }
// Ensure LRUCache implements Cache.
var _ Cache = &LRUCache{}
var _ cache = &lruCache{}
// RankCache represents a cache with sorted entries.
type RankCache struct {
mu sync.Mutex
entries map[uint64]uint64
rankings []BitmapPair // cached, ordered list
// rankCache represents a cache with sorted entries.
type rankCache struct {
// TODO why does this have a lock and lruCache doesn't?
mu sync.Mutex
entries map[uint64]uint64
rankings bitmapPairs // cached, ordered list
rankingsRead bool
dirty bool
updateN int
updateTime time.Time
@ -150,26 +147,46 @@ type RankCache struct {
// thresholdValue is the value of the last item in the cache
thresholdValue uint64
stats StatsClient
}
// NewRankCache returns a new instance of RankCache.
func NewRankCache(maxEntries uint32) *RankCache {
return &RankCache{
func NewRankCache(maxEntries uint32) *rankCache {
return &rankCache{
maxEntries: maxEntries,
thresholdBuffer: int(ThresholdFactor * float64(maxEntries)),
thresholdBuffer: int(thresholdFactor * float64(maxEntries)),
entries: make(map[uint64]uint64),
stats: NopStatsClient,
}
}
// Add adds a count to the cache.
func (c *RankCache) Add(id uint64, n uint64) {
func (c *rankCache) Clear() {
c.mu.Lock()
defer c.mu.Unlock()
// Ignore if the bit count is below the threshold.
if n < c.thresholdValue {
for k := range c.entries {
delete(c.entries, k)
}
c.rankings = c.rankings[:0]
c.rankingsRead = false
c.dirty = false
c.updateN = 0
c.updateTime = time.Time{}
c.thresholdValue = 0
}
// Add adds a count to the cache.
func (c *rankCache) Add(id uint64, n uint64) {
c.mu.Lock()
defer c.mu.Unlock()
// Flag the cache as dirty.
// This forces recalculation if top is called before the cache is recalculated.
c.dirty = true
// Ignore if the column count is below the threshold,
// unless the count is 0, which is effectively used
// to clear the cache value.
if n < c.thresholdValue && n > 0 {
delete(c.entries, id)
return
}
@ -179,84 +196,116 @@ func (c *RankCache) Add(id uint64, n uint64) {
}
// BulkAdd adds a count to the cache unsorted. You should Invalidate after completion.
func (c *RankCache) BulkAdd(id uint64, n uint64) {
func (c *rankCache) BulkAdd(id uint64, n uint64) {
c.mu.Lock()
defer c.mu.Unlock()
// Flag the cache as dirty.
// This forces recalculation if top is called before the cache is recalculated.
c.dirty = true
if n < c.thresholdValue {
delete(c.entries, id)
return
}
c.entries[id] = n
// FB-1206: Periodically invalidate the cache when we are bulk loading
// as this can take up an upbounded amount of memory. This is especially
// true when restoring shards as all rows will be added.
if len(c.entries) > int(2*c.maxEntries) {
CounterRecalculateCache.Inc()
c.recalculate()
}
}
// Get returns a count for a given id.
func (c *RankCache) Get(id uint64) uint64 {
func (c *rankCache) Get(id uint64) uint64 {
c.mu.Lock()
defer c.mu.Unlock()
return c.entries[id]
}
// Len returns the number of items in the cache.
func (c *RankCache) Len() int {
func (c *rankCache) Len() int {
c.mu.Lock()
defer c.mu.Unlock()
return len(c.entries)
}
// IDs returns a list of all IDs in the cache.
func (c *RankCache) IDs() []uint64 {
func (c *rankCache) IDs() []uint64 {
c.mu.Lock()
defer c.mu.Unlock()
a := make([]uint64, 0, len(c.entries))
for id := range c.entries {
a = append(a, id)
if len(c.entries) == 0 {
return nil
}
sort.Sort(uint64Slice(a))
return a
ids := make([]uint64, 0, len(c.entries))
for id := range c.entries {
ids = append(ids, id)
}
sort.Sort(uint64Slice(ids))
return ids
}
// Invalidate recalculates the entries by rank.
func (c *RankCache) Invalidate() {
func (c *rankCache) Invalidate() {
c.mu.Lock()
defer c.mu.Unlock()
c.invalidate()
}
// Recalculate rebuilds the cache.
func (c *RankCache) Recalculate() {
func (c *rankCache) Recalculate() {
c.mu.Lock()
defer c.mu.Unlock()
c.stats.Count("cache.recalculate", 1, 1.0)
CounterRecalculateCache.Inc()
c.recalculate()
}
func (c *RankCache) invalidate() {
func (c *rankCache) invalidate() {
// Don't invalidate more than once every X seconds.
// TODO: consider making this configurable.
if time.Now().Sub(c.updateTime).Seconds() < 10 {
if time.Since(c.updateTime).Seconds() < 10 {
// Skipping recalculation means that the ranked cache's growth is unbounded.
// This is somewhat necessary for now since recalculation is not cheap.
// The cache will remain flagged as dirty and will be recalculated if Top is called.
// This may cause unexpected memory growth, so record it in metrics for debugging purposes.
CounterInvalidateCacheSkipped.Inc()
// Ensure that we're marked as dirty even if we weren't otherwise.
c.dirty = true
return
}
c.stats.Count("cache.invalidate", 1, 1.0)
CounterInvalidateCache.Inc()
c.recalculate()
}
func (c *RankCache) recalculate() {
func (c *rankCache) recalculate() {
if c.rankingsRead {
c.rankings = nil
c.rankingsRead = false
}
// Convert cache to a sorted list.
rankings := make([]BitmapPair, 0, len(c.entries))
rankings := c.rankings[:0]
if cap(rankings) < len(c.entries) {
rankings = make([]bitmapPair, 0, len(c.entries))
}
for id, cnt := range c.entries {
rankings = append(rankings, BitmapPair{
rankings = append(rankings, bitmapPair{
ID: id,
Count: cnt,
})
}
sort.Sort(BitmapPairs(rankings))
c.rankings = rankings
sort.Sort(&c.rankings)
// Store the count of the item at the threshold index.
c.rankings = rankings
length := len(c.rankings)
c.stats.Gauge("RankCache", float64(length), 1.0)
GaugeRankCacheLength.Set(float64(length))
var removeItems []BitmapPair // cached, ordered list
var removeItems []bitmapPair // cached, ordered list
if length > int(c.maxEntries) {
c.thresholdValue = rankings[c.maxEntries].Count
removeItems = c.rankings[c.maxEntries:]
@ -270,67 +319,115 @@ func (c *RankCache) recalculate() {
// If size is larger than the threshold then trim it.
if len(c.entries) > c.thresholdBuffer {
c.stats.Count("cache.threshold", 1, 1.0)
CounterCacheThresholdReached.Inc()
for _, pair := range removeItems {
delete(c.entries, pair.ID)
}
}
}
// SetStats defines the stats client used in the cache.
func (c *RankCache) SetStats(s StatsClient) {
c.stats = s
// The cache is no longer dirty.
c.dirty = false
}
// Top returns an ordered list of pairs.
func (c *RankCache) Top() []BitmapPair { return c.rankings }
func (c *rankCache) Top() []bitmapPair {
c.mu.Lock()
defer c.mu.Unlock()
if c.dirty {
// The cache is dirty, so we need to recalculate it to get a consistent view.
CounterReadDirtyCache.Inc()
c.recalculate()
}
c.rankingsRead = true
return c.rankings
}
// WriteTo writes the cache to w.
func (c *RankCache) WriteTo(w io.Writer) (n int64, err error) {
func (c *rankCache) WriteTo(w io.Writer) (n int64, err error) {
panic("FIXME: TODO")
}
// ReadFrom read from r into the cache.
func (c *RankCache) ReadFrom(r io.Reader) (n int64, err error) {
func (c *rankCache) ReadFrom(r io.Reader) (n int64, err error) {
panic("FIXME: TODO")
}
// Ensure RankCache implements Cache.
var _ Cache = &RankCache{}
var _ cache = &rankCache{}
// BitmapPair represents a id/count pair with an associated identifier.
type BitmapPair struct {
// bitmapPair represents a id/count pair with an associated identifier.
type bitmapPair struct {
ID uint64
Count uint64
}
// BitmapPairs is a sortable list of BitmapPair objects.
type BitmapPairs []BitmapPair
// bitmapPairs is a sortable list of BitmapPair objects.
type bitmapPairs []bitmapPair
func (p BitmapPairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p BitmapPairs) Len() int { return len(p) }
func (p BitmapPairs) Less(i, j int) bool { return p[i].Count > p[j].Count }
func (p *bitmapPairs) Swap(i, j int) { (*p)[i], (*p)[j] = (*p)[j], (*p)[i] }
func (p *bitmapPairs) Len() int { return len(*p) }
func (p *bitmapPairs) Less(i, j int) bool { return (*p)[i].Count > (*p)[j].Count }
// Pair holds an id/count pair.
type Pair struct {
ID uint64 `json:"id"`
Key string `json:"key"`
Count uint64 `json:"count"`
}
func encodePair(p Pair) *internal.Pair {
return &internal.Pair{
Key: p.ID,
Count: p.Count,
// PairField is a Pair with its associated field.
type PairField struct {
Pair Pair
Field string
}
func (p PairField) Clone() (r PairField) {
return PairField{
Pair: p.Pair,
Field: p.Field,
}
}
func decodePair(pb *internal.Pair) Pair {
return Pair{
ID: pb.Key,
Count: pb.Count,
// ToTable implements the ToTabler interface.
func (p PairField) ToTable() (*pb.TableResponse, error) {
return pb.RowsToTable(p, 1)
}
// ToRows implements the ToRowser interface.
func (p PairField) ToRows(callback func(*pb.RowResponse) error) error {
if p.Pair.Key != "" {
return callback(&pb.RowResponse{
Headers: []*pb.ColumnInfo{
{Name: p.Field, Datatype: "string"},
{Name: "count", Datatype: "uint64"},
},
Columns: []*pb.ColumnResponse{
{ColumnVal: &pb.ColumnResponse_StringVal{StringVal: p.Pair.Key}},
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: p.Pair.Count}},
},
})
} else {
return callback(&pb.RowResponse{
Headers: []*pb.ColumnInfo{
{Name: p.Field, Datatype: "uint64"},
{Name: "count", Datatype: "uint64"},
},
Columns: []*pb.ColumnResponse{
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: p.Pair.ID}},
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: p.Pair.Count}},
},
})
}
}
// MarshalJSON marshals PairField into a JSON-encoded byte slice,
// excluding `Field`.
func (p PairField) MarshalJSON() ([]byte, error) {
return json.Marshal(p.Pair)
}
// Pairs is a sortable slice of Pair objects.
type Pairs []Pair
@ -338,14 +435,14 @@ func (p Pairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Pairs) Len() int { return len(p) }
func (p Pairs) Less(i, j int) bool { return p[i].Count > p[j].Count }
// PairHeap is a heap implementation over a group of Pairs.
type PairHeap struct {
// pairHeap is a heap implementation over a group of Pairs.
type pairHeap struct {
Pairs
}
// Less implemets the Sort interface.
// reports whether the element with index i should sort before the element with index j.
func (p PairHeap) Less(i, j int) bool { return p.Pairs[i].Count < p.Pairs[j].Count }
func (p pairHeap) Less(i, j int) bool { return p.Pairs[i].Count < p.Pairs[j].Count }
// Push appends the element onto the Pair slice.
func (p *Pairs) Push(x interface{}) {
@ -406,22 +503,82 @@ func (p Pairs) String() string {
return buf.String()
}
func encodePairs(a Pairs) []*internal.Pair {
other := make([]*internal.Pair, len(a))
for i := range a {
other[i] = encodePair(a[i])
}
return other
// PairsField is a Pairs object with its associated field.
type PairsField struct {
Pairs []Pair
Field string
}
func decodePairs(a []*internal.Pair) []Pair {
other := make([]Pair, len(a))
for i := range a {
other[i] = decodePair(a[i])
func (p *PairsField) Clone() (r *PairsField) {
r = &PairsField{
Pairs: make([]Pair, len(p.Pairs)),
Field: p.Field,
}
return other
copy(r.Pairs, p.Pairs)
return
}
// ToTable implements the ToTabler interface.
func (p *PairsField) ToTable() (*pb.TableResponse, error) {
return pb.RowsToTable(p, len(p.Pairs))
}
// ToRows implements the ToRowser interface.
func (p *PairsField) ToRows(callback func(*pb.RowResponse) error) error {
// Determine if the ID has string keys.
var stringKeys bool
if len(p.Pairs) > 0 {
if p.Pairs[0].Key != "" {
stringKeys = true
}
}
dtype := "uint64"
if stringKeys {
dtype = "string"
}
ci := []*pb.ColumnInfo{
{Name: p.Field, Datatype: dtype},
{Name: "count", Datatype: "uint64"},
}
for _, pair := range p.Pairs {
if stringKeys {
if err := callback(&pb.RowResponse{
Headers: ci,
Columns: []*pb.ColumnResponse{
{ColumnVal: &pb.ColumnResponse_StringVal{StringVal: pair.Key}},
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: uint64(pair.Count)}},
}}); err != nil {
return errors.Wrap(err, "calling callback")
}
} else {
if err := callback(&pb.RowResponse{
Headers: ci,
Columns: []*pb.ColumnResponse{
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: uint64(pair.ID)}},
{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: uint64(pair.Count)}},
}}); err != nil {
return errors.Wrap(err, "calling callback")
}
}
ci = nil //only send on the first
}
return nil
}
// MarshalJSON marshals PairsField into a JSON-encoded byte slice,
// excluding `Field`.
func (p PairsField) MarshalJSON() ([]byte, error) {
return json.Marshal(p.Pairs)
}
// int64Slice represents a sortable slice of int64 numbers.
type int64Slice []int64
func (p int64Slice) Len() int { return len(p) }
func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// uint64Slice represents a sortable slice of uint64 numbers.
type uint64Slice []uint64
@ -429,89 +586,23 @@ func (p uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p uint64Slice) Len() int { return len(p) }
func (p uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
// merge combines p and other to a unique sorted set of values.
// p and other must both have unique sets and be sorted.
func (p uint64Slice) merge(other []uint64) []uint64 {
ret := make([]uint64, 0, len(p))
i, j := 0, 0
for i < len(p) && j < len(other) {
a, b := p[i], other[j]
if a == b {
ret = append(ret, a)
i, j = i+1, j+1
} else if a < b {
ret = append(ret, a)
i++
} else {
ret = append(ret, b)
j++
}
}
if i < len(p) {
ret = append(ret, p[i:]...)
} else if j < len(other) {
ret = append(ret, other[j:]...)
}
return ret
}
// BitmapCache provides an interface for caching full bitmaps.
type BitmapCache interface {
Fetch(id uint64) (*Bitmap, bool)
Add(id uint64, b *Bitmap)
}
// SimpleCache implements BitmapCache
// it is meant to be a short-lived cache for cases where writes are continuing to access
// the same bit within a short time frame (i.e. good for write-heavy loads)
// A read-heavy use case would cause the cache to get bigger, potentially causing the
// node to run out of memory.
type SimpleCache struct {
cache map[uint64]*Bitmap
}
// Fetch retrieves the bitmap at the id in the cache.
func (s *SimpleCache) Fetch(id uint64) (*Bitmap, bool) {
m, ok := s.cache[id]
return m, ok
}
// Add adds the bitmap to the cache, keyed on the id.
func (s *SimpleCache) Add(id uint64, b *Bitmap) {
s.cache[id] = b
}
// NopCache represents a no-op Cache implementation.
type NopCache struct {
stats StatsClient
}
// nopCache represents a no-op Cache implementation.
type nopCache struct{}
// Ensure NopCache implements Cache.
var _ Cache = &NopCache{}
var globalNopCache cache = nopCache{}
// NewNopCache returns a new instance of NopCache.
func NewNopCache() *NopCache {
return &NopCache{
stats: NopStatsClient,
}
}
func (c nopCache) Add(uint64, uint64) {}
func (c nopCache) BulkAdd(uint64, uint64) {}
func (c nopCache) Get(uint64) uint64 { return 0 }
func (c nopCache) IDs() []uint64 { return []uint64{} }
func (c *NopCache) Add(id uint64, n uint64) {}
func (c *NopCache) BulkAdd(id uint64, n uint64) {}
func (c *NopCache) Get(id uint64) uint64 { return 0 }
func (c *NopCache) IDs() []uint64 { return make([]uint64, 0, 0) }
func (c nopCache) Invalidate() {}
func (c nopCache) Len() int { return 0 }
func (c nopCache) Recalculate() {}
func (c *NopCache) Invalidate() {}
func (c *NopCache) Len() int { return 0 }
func (c *NopCache) Recalculate() {
}
func (c *NopCache) SetStats(s StatsClient) {
c.stats = s
}
func (c nopCache) Clear() {}
func (c *NopCache) Top() []BitmapPair {
return []BitmapPair{}
func (c nopCache) Top() []bitmapPair {
return []bitmapPair{}
}

View file

@ -1,27 +1,16 @@
// Copyright 2017 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa_test
import (
"reflect"
"testing"
"github.com/pilosa/pilosa"
pilosa "github.com/featurebasedb/featurebase/v3"
)
// Ensure a bitmap query can be executed.
func TestCache_Rank(t *testing.T) {
// Ensure cache stays constrained to its configured size.
func TestCache_Rank_Size(t *testing.T) {
cacheSize := uint32(3)
cache := pilosa.NewRankCache(cacheSize)
for i := 1; i < int(2*cacheSize); i++ {
@ -31,5 +20,66 @@ func TestCache_Rank(t *testing.T) {
if cache.Len() != int(cacheSize) {
t.Fatalf("unexpected cache Size: %d!=%d expected\n", cache.Len(), cacheSize)
}
}
// Ensure cache entries set below threshold are handled appropriately.
func TestCache_Rank_Threshold(t *testing.T) {
cacheSize := uint32(5)
cache := pilosa.NewRankCache(cacheSize)
for i := 1; i < int(2*cacheSize); i++ {
cache.Add(uint64(i), 3)
}
// Set the cache value for rows 4 and 5 to a number below the threshold
// value (which is 3), and ensure that they gets zeroed out.
cache.Add(4, 1)
cache.BulkAdd(5, 1)
cache.Recalculate()
if cache.Get(4) != 0 {
t.Fatalf("unexpected cache value after Add: %d!=%d expected\n", cache.Get(4), 0)
}
if cache.Get(5) != 0 {
t.Fatalf("unexpected cache value after BulkAdd: %d!=%d expected\n", cache.Get(5), 0)
}
}
// Test that consecutive writes show up in Top.
// On later writes, the cache skips recalculation to save CPU time.
// This used to mean that the later writes would not show up in Top.
// Now, the cache is flagged as dirty and recalculated during the call to Top.
func TestCache_Rank_Dirty(t *testing.T) {
cacheSize := uint32(5)
cache := pilosa.NewRankCache(cacheSize)
type pair struct{ ID, Count uint64 }
expect := []pair{
{5, 2},
{4, 1},
}
for _, v := range expect {
cache.Add(v.ID, v.Count)
}
var got []pair //nolint:prealloc
for _, p := range cache.Top() {
got = append(got, pair(p))
}
if !reflect.DeepEqual(expect, got) {
t.Fatalf("wrote %v but got %v", expect, got)
}
}
func TestCache_Rank_BulkAdd(t *testing.T) {
const cacheSize = 10
cache := pilosa.NewRankCache(uint32(cacheSize))
for i := uint64(0); i < 1000; i++ {
cache.BulkAdd(i, i)
if n := cache.Len(); n > cacheSize*2 {
t.Fatalf("entry count exceed 2x cache size: %d", n)
}
}
}

233
catcher.go Normal file
View file

@ -0,0 +1,233 @@
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"github.com/featurebasedb/featurebase/v3/roaring"
txkey "github.com/featurebasedb/featurebase/v3/short_txkey"
"github.com/featurebasedb/featurebase/v3/vprint"
)
// catcher is useful to report error locations with a
// Stack dump before the complexity
// of the executor_test swallows up
// the location of a PanicOn.
type catcherTx struct {
b Tx
}
func newCatcherTx(b Tx) *catcherTx {
return &catcherTx{b: b}
}
func init() {
// keep golangci-lint happy
_ = newCatcherTx
}
var _ Tx = (*catcherTx)(nil)
func (c *catcherTx) ImportRoaringBits(index, field, view string, shard uint64, rit roaring.RoaringIterator, clear bool, log bool, rowSize uint64) (changed int, rowSet map[uint64]int, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see ImportRoaringBits() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.ImportRoaringBits(index, field, view, shard, rit, clear, log, rowSize)
}
func (c *catcherTx) Rollback() {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Rollback() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
c.b.Rollback()
}
func (c *catcherTx) Commit() error {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Commit() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Commit()
}
func (c *catcherTx) RoaringBitmap(index, field, view string, shard uint64) (*roaring.Bitmap, error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see RoaringBitmap() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.RoaringBitmap(index, field, view, shard)
}
func (c *catcherTx) Container(index, field, view string, shard uint64, key uint64) (ct *roaring.Container, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Container() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Container(index, field, view, shard, key)
}
func (c *catcherTx) PutContainer(index, field, view string, shard uint64, key uint64, rc *roaring.Container) error {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see PutContainer() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.PutContainer(index, field, view, shard, key, rc)
}
func (c *catcherTx) RemoveContainer(index, field, view string, shard uint64, key uint64) error {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see RemoveContainer() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.RemoveContainer(index, field, view, shard, key)
}
func (c *catcherTx) Add(index, field, view string, shard uint64, a ...uint64) (changeCount int, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Add() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Add(index, field, view, shard, a...)
}
func (c *catcherTx) Remove(index, field, view string, shard uint64, a ...uint64) (changeCount int, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Remove() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Remove(index, field, view, shard, a...)
}
func (c *catcherTx) Removed(index, field, view string, shard uint64, a ...uint64) (changed []uint64, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Removed() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Removed(index, field, view, shard, a...)
}
func (c *catcherTx) Contains(index, field, view string, shard uint64, key uint64) (exists bool, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Contains() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Contains(index, field, view, shard, key)
}
func (c *catcherTx) ContainerIterator(index, field, view string, shard uint64, firstRoaringContainerKey uint64) (citer roaring.ContainerIterator, found bool, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see ContainerIterator() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.ContainerIterator(index, field, view, shard, firstRoaringContainerKey)
}
func (c *catcherTx) Count(index, field, view string, shard uint64) (uint64, error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Count() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Count(index, field, view, shard)
}
func (c *catcherTx) Max(index, field, view string, shard uint64) (uint64, error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Max() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Max(index, field, view, shard)
}
func (c *catcherTx) Min(index, field, view string, shard uint64) (uint64, bool, error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see Min() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.Min(index, field, view, shard)
}
func (c *catcherTx) CountRange(index, field, view string, shard uint64, start, end uint64) (n uint64, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see CountRange() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.CountRange(index, field, view, shard, start, end)
}
func (c *catcherTx) OffsetRange(index, field, view string, shard, offset, start, end uint64) (other *roaring.Bitmap, err error) {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see OffsetRange() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.OffsetRange(index, field, view, shard, offset, start, end)
}
func (c *catcherTx) Type() string {
return c.b.Type()
}
func (c *catcherTx) ApplyFilter(index, field, view string, shard uint64, ckey uint64, filter roaring.BitmapFilter) (err error) {
return GenericApplyFilter(c, index, field, view, shard, ckey, filter)
}
func (c *catcherTx) ApplyRewriter(index, field, view string, shard uint64, ckey uint64, filter roaring.BitmapRewriter) (err error) {
return c.b.ApplyRewriter(index, field, view, shard, ckey, filter)
}
func (c *catcherTx) GetSortedFieldViewList(idx *Index, shard uint64) (fvs []txkey.FieldView, err error) {
return c.b.GetSortedFieldViewList(idx, shard)
}
func (c *catcherTx) GetFieldSizeBytes(index, field string) (uint64, error) {
return 0, nil
}

15
cli/Makefile Normal file
View file

@ -0,0 +1,15 @@
.PHONY: test testv test-integration testv-integration
GO=go
test:
$(GO) test ./... -short
testv:
$(GO) test -v ./... -short
test-integration:
$(GO) test . -count 1 -timeout 20m -run TestCLIIntegration/$(RUN)
testv-integration:
$(GO) test -v . -count 1 -timeout 20m -run TestCLIIntegration/$(RUN)

8
cli/batch/inserter.go Normal file
View file

@ -0,0 +1,8 @@
package batch
// Inserter can be implemented by anything which can handle a SQL statement
// representing a write operation. An example is `BULK INSERT`. The Insert()
// method on this interface does not return any results other than an error.
type Inserter interface {
Insert(sql string) error
}

215
cli/batch/sql.go Normal file
View file

@ -0,0 +1,215 @@
package batch
import (
"encoding/json"
"fmt"
"strings"
"time"
fbbatch "github.com/featurebasedb/featurebase/v3/batch"
"github.com/featurebasedb/featurebase/v3/dax"
"github.com/featurebasedb/featurebase/v3/errors"
"github.com/featurebasedb/featurebase/v3/pql"
)
// Ensure type implements interface.
var _ fbbatch.Batcher = (*sqlBatcher)(nil)
type sqlBatcher struct {
inserter Inserter
fields []*dax.Field
}
func NewSQLBatcher(i Inserter, flds []*dax.Field) *sqlBatcher {
return &sqlBatcher{
inserter: i,
fields: flds,
}
}
func (b *sqlBatcher) NewBatch(cfg fbbatch.Config, tbl *dax.Table, flds []*dax.Field) (fbbatch.RecordBatch, error) {
fields := flds
if b.fields != nil {
fields = b.fields
}
return &sqlBatch{
table: tbl,
fields: fields,
size: cfg.Size,
maxStaleness: cfg.MaxStaleness,
ids: make([]interface{}, 0, cfg.Size),
rows: make([][]interface{}, 0, cfg.Size),
inserter: b.inserter,
}, nil
}
// Ensure type implements interface.
var _ fbbatch.RecordBatch = (*sqlBatch)(nil)
type sqlBatch struct {
table *dax.Table
fields []*dax.Field
size int
ids []interface{}
rows [][]interface{}
// staleTime tracks the time the first record of the batch was inserted
// plus the maxStaleness, in order to raise ErrBatchNowStale if the
// maxStaleness has elapsed
staleTime time.Time
maxStaleness time.Duration
// inserter handles SQL INSERT statements generated for each batch.
inserter Inserter
}
func (b *sqlBatch) Add(rec fbbatch.Row) error {
// Clear rec.Values and rec.Clears upon return.
defer func() {
for i := range rec.Values {
rec.Values[i] = nil
}
for k := range rec.Clears {
delete(rec.Clears, k)
}
}()
if len(b.ids) == cap(b.ids) {
return fbbatch.ErrBatchAlreadyFull
}
if len(rec.Values) != len(b.fields) {
return errors.Errorf("record needs to match up with batch fields, got %d fields and %d record", len(b.fields), len(rec.Values))
}
// Append the ID to b.ids.
b.ids = append(b.ids, rec.ID)
// Convert decimal fields (which come in as int64, along with the scale in
// field) to pql.Decimal.
for i, fld := range b.fields {
switch b.fields[i].Type {
case dax.BaseTypeDecimal:
if val, ok := rec.Values[i].(int64); ok {
rec.Values[i] = pql.NewDecimal(val, fld.Options.Scale)
}
case dax.BaseTypeTimestamp:
if val, ok := rec.Values[i].(int64); ok {
ts := time.Unix(val, 0)
rec.Values[i] = ts.Format(time.RFC3339)
}
}
}
// Append the record to b.rows.
vals := make([]interface{}, 0, len(rec.Values))
vals = append(vals, rec.Values...)
b.rows = append(b.rows, vals)
// Check for batch full or stale.
if len(b.ids) == cap(b.ids) {
return fbbatch.ErrBatchNowFull
}
if b.maxStaleness != time.Duration(0) { // set maxStaleness to 0 to disable staleness checking
if len(b.ids) == 1 {
b.staleTime = time.Now().Add(b.maxStaleness)
} else if time.Now().After(b.staleTime) {
return fbbatch.ErrBatchNowStale
}
}
return nil
}
func (b *sqlBatch) Import() error {
if len(b.rows) == 0 {
return nil
}
// Construct the BULK INSERT statement based on the table and fields.
sql, err := buildBulkInsert(b.table, b.fields, b.ids, b.rows)
if err != nil {
return errors.Wrap(err, "building bulk insert statement")
}
// Reset batch data.
b.reset()
// Submit the SQL statement.
return b.inserter.Insert(sql)
}
func (b *sqlBatch) reset() {
b.ids = b.ids[:0]
b.rows = b.rows[:0]
}
func (b *sqlBatch) Len() int {
return len(b.rows)
}
func (b *sqlBatch) Flush() error {
return nil
}
func buildBulkInsert(tbl *dax.Table, fields []*dax.Field, ids []interface{}, rows [][]interface{}) (string, error) {
// Validation.
if tbl.Name == "" {
return "", errors.New(errors.ErrUncoded, "table name is required")
} else if len(fields) == 0 {
return "", errors.New(errors.ErrUncoded, "at least one field is required")
}
var sb strings.Builder
sb.WriteString(`BULK INSERT INTO `)
sb.WriteString(string(tbl.Name))
sb.WriteString(` (_id,`)
flds := make([]string, 0, len(fields))
maps := make([]string, 0, len(fields))
for i := range fields {
flds = append(flds, string(fields[i].Name))
maps = append(maps, fmt.Sprintf("'$.col_%d' %s", i, fields[i].FullType()))
}
// Fields
sb.WriteString(strings.Join(flds, ","))
// MAP
keyType := dax.BaseTypeID
if tbl.StringKeys() {
keyType = dax.BaseTypeString
}
sb.WriteString(`) MAP ('$._id' `)
sb.WriteString(keyType)
sb.WriteString(`,`)
sb.WriteString(strings.Join(maps, ","))
sb.WriteString(`) FROM x'`)
// Row values.
// m is a map representing a single row to be marshalled and added to the
// bulk insert as one line in the NDJSON payload. We re-use the map for each
// row.
m := make(map[string]interface{})
for i := range rows {
// Write the ID value.
m[string(dax.PrimaryKeyFieldName)] = ids[i]
// Write the rest of the data values.
for col := range rows[i] {
m[fmt.Sprintf("col_%d", col)] = rows[i][col]
}
// Marshal the map to json and add to the sql statement.
if j, err := json.Marshal(m); err != nil {
return "", errors.Wrap(err, "marshalling row to json")
} else {
sb.Write(j)
sb.WriteString("\n")
}
}
// WITH
sb.WriteString(fmt.Sprintf(`' WITH BATCHSIZE %d FORMAT 'NDJSON' INPUT 'STREAM'`, len(rows)))
return sb.String(), nil
}

47
cli/batch/sql_test.go Normal file
View file

@ -0,0 +1,47 @@
package batch
import (
"testing"
"github.com/featurebasedb/featurebase/v3/dax"
"github.com/stretchr/testify/assert"
)
func TestBatchSQL(t *testing.T) {
tbl := &dax.Table{
Name: "foo",
}
fields := []*dax.Field{
{
Name: "name",
Type: dax.BaseTypeString,
},
{
Name: "age",
Type: dax.BaseTypeInt,
},
}
ids := []interface{}{
0, 1, 2,
}
rows := [][]interface{}{
{
[]interface{}{"Alice", int64(11)},
},
{
[]interface{}{"Bob", int64(22)},
},
{
[]interface{}{"Carl,Comma", int64(33)},
},
}
s, err := buildBulkInsert(tbl, fields, ids, rows)
assert.NoError(t, err)
exp := `BULK INSERT INTO foo (_id,name,age) MAP ('$._id' id,'$.col_0' string,'$.col_1' int) FROM x'{"_id":0,"col_0":["Alice",11]}
{"_id":1,"col_0":["Bob",22]}
{"_id":2,"col_0":["Carl,Comma",33]}
' WITH BATCHSIZE 3 FORMAT 'NDJSON' INPUT 'STREAM'`
assert.Equal(t, exp, s)
}

91
cli/buffer.go Normal file
View file

@ -0,0 +1,91 @@
package cli
import (
"io"
"strings"
"github.com/featurebasedb/featurebase/v3/errors"
)
// buffer is a query buffer for SQL statements. Note that this is not a query
// buffer as you would find on a database server (buffering query results).
// Rather, this buffers the working SQL statement. The buffer has two
// components: the buffer of query parts making up the working, incomplete SQL
// statement, and the last completed SQL statement submitted to the Queryer.
type buffer struct {
parts []queryPart
lastQuery query
hasBatchFile bool
}
func newBuffer() *buffer {
return &buffer{}
}
// addPart adds the given queryPart to the buffer. If the part is of type
// `partTerminator` (which is generally singified in the CLI by a ";"), the
// buffer will finalize the query and return it. In all other cases, the
// returned query is nil.
func (b *buffer) addPart(part queryPart) (query, error) {
// Check for part type compatibility. For example, multiple batchFile parts
// are not allowed in the same query.
switch part.(type) {
case *partBatchFile:
if b.hasBatchFile {
return nil, errors.Errorf("multiple batch files in one query is not supported")
}
b.hasBatchFile = true
case *partTerminator:
return b.finalize(), nil
}
b.parts = append(b.parts, part)
return nil, nil
}
// finalize copies the contents (queryParts) of buffer to lastQuery and then
// resets the buffer. It returns the query that was finalized.
func (b *buffer) finalize() query {
q := make(query, len(b.parts))
copy(q, b.parts)
b.lastQuery = q
b.reset()
return q
}
// print returns the contents of the buffer as a string. This is generally used
// to visually inspect the state of the buffer (for example, when a user issues
// a `\p` meta-command in the CLI).
func (b *buffer) print() string {
if len(b.parts) > 0 {
return query(b.parts).String()
} else if b.lastQuery != nil {
return b.lastQuery.String() + ";"
}
return "Query buffer is empty."
}
// reset clears the buffer. It returns a message which may optionally be used to
// display to a user.
func (b *buffer) reset() string {
b.parts = b.parts[:0]
b.hasBatchFile = false
return "Query buffer reset (cleared)."
}
func (b *buffer) Reader() io.Reader {
if len(b.parts) > 0 {
return query(b.parts).Reader()
} else if b.lastQuery != nil {
r := b.lastQuery.Reader()
// TODO(tlt): terminating the query here results in a line feed just
// before the semi-colon (for example, when you print out the query
// buffer using `\w [FILE]`). The removal and re-introduction of line
// feeds is kind of a mess.
term := strings.NewReader(";")
return io.MultiReader(r, term)
}
return strings.NewReader("")
}

816
cli/cli.go Normal file
View file

@ -0,0 +1,816 @@
// Package cli contains a FeatureBase command line interface.
package cli
import (
"context"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/chzyer/readline"
featurebase "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/cli/batch"
"github.com/featurebasedb/featurebase/v3/cli/fbcloud"
"github.com/featurebasedb/featurebase/v3/errors"
"github.com/featurebasedb/featurebase/v3/logger"
)
const (
defaultHost string = "localhost"
defaultClientID string = "6i2gs7mu215ab23cnvmshdoq6t" // production Cognito client ID
defaultRegion string = "us-east-2"
terminationChar string = ";"
nullValue string = "NULL"
)
var (
Stdin io.ReadCloser = os.Stdin
Stdout io.Writer = os.Stdout
Stderr io.Writer = os.Stderr
)
var splash string = fmt.Sprintf(`FeatureBase CLI (%s)
Type "\q" to quit.
`, featurebase.Version)
// Ensure type implments interfaces.
var _ printer = (*Command)(nil)
var _ batch.Inserter = (*Command)(nil)
type Command struct {
host string
port string
splitter *splitter
buffer *buffer
workingDir *workingDir
organizationID string
database string
databaseID string
databaseName string
Queryer Queryer `json:"-"`
stdin io.ReadCloser `json:"-"`
stdout io.Writer `json:"-"`
stderr io.Writer `json:"-"`
// output is where actual results are written. This might point to stdout,
// or to a file, based on the current configuration.
output io.Writer `json:"-"`
writeOptions *writeOptions
Config *Config `json:"config"`
historyPath string
// Commands contains optional commands provided via one or more `-c` (or
// `--command`) flags. If this is non-empty, the cli will run in
// non-interactive mode; i.e. it will quit after the command is complete.
Commands []string `json:"commands"`
// Files contains optional files provided via one or more `-f` (or `--file`)
// flags. If this is non-empty, the cli will run in non-interactive mode;
// i.e. it will quit after the command is complete.
Files []string `json:"files"`
// variables holds the variables created with the \set meta-command.
variables map[string]string
// nonInteractiveMode is set to true when fbsql is running in
// non-ineracative mode. And example of this is when the user has provided a
// `-c` flag in the command line.
nonInteractiveMode bool
// quit gets closed when Run should stop listening for input.
quit chan struct{}
}
func NewCommand(logdest logger.Logger) *Command {
variables := make(map[string]string)
return &Command{
Config: &Config{
Host: defaultHost,
Port: "",
OrganizationID: "",
Database: "",
CloudAuth: CloudAuthConfig{
ClientID: defaultClientID,
Region: defaultRegion,
Email: "",
Password: "",
},
HistoryPath: "",
CSV: false,
},
buffer: newBuffer(),
splitter: newSplitter(newReplacer(variables)),
workingDir: newWorkingDir(),
stdin: Stdin,
stdout: Stdout,
stderr: Stderr,
output: Stdout,
writeOptions: defaultWriteOptions(),
variables: variables,
quit: make(chan struct{}),
}
}
// SetStdin sets stdin. This is useful for initial configuration in tests.
func (cmd *Command) SetStdin(rc io.ReadCloser) {
cmd.stdin = rc
}
// SetStdout sets both stdout and output to the value provided. This is useful
// for initial configuration in tests.
func (cmd *Command) SetStdout(w io.Writer) {
cmd.stdout = w
cmd.output = w
}
// SetStderr sets stderr. This is useful for initial configuration in tests.
func (cmd *Command) SetStderr(w io.Writer) {
cmd.stderr = w
}
// Run is the main entry-point to the CLI.
func (cmd *Command) Run(ctx context.Context) error {
if err := cmd.run(ctx); err != nil {
cmd.Errorf(err.Error() + "\n")
return err
}
return nil
}
// run is effectively wrapped by the Run() method, but it's split out this way
// so that run() can simply return errors, rather than worrying about how errors
// should be printed; printing errors returned by run() is left up to the Run()
// method.
func (cmd *Command) run(ctx context.Context) error {
if err := cmd.setupConfig(); err != nil {
return errors.Wrap(err, "setting up config")
}
// Check to see if Command needs to run in non-interactive mode.
if len(cmd.Commands) > 0 ||
len(cmd.Files) > 0 ||
cmd.Config.KafkaConfig != "" ||
cmd.Config.CSV {
cmd.nonInteractiveMode = true
}
// Print the splash message.
if !cmd.nonInteractiveMode {
cmd.Printf(splash)
}
if err := cmd.setupClient(); err != nil {
return errors.Wrap(err, "setting up client")
}
// Print the connection info.
if !cmd.nonInteractiveMode {
cmd.printConnInfo()
}
if err := cmd.connectToDatabase(cmd.database); err != nil {
cmd.Errorf(errors.Wrap(err, "connecting to database").Error() + "\n")
// We intentionally do not return err here.
}
// Run in non-interactive mode based on flags and configuration.
// This includes either handling `-c` and/or `-f` flags, or handling a
// `--kafka-config` flag.
if len(cmd.Commands) > 0 || len(cmd.Files) > 0 {
// Run Commands.
for _, line := range cmd.Commands {
if err := cmd.handleLine(line); err != nil {
return errors.Wrapf(err, "handling line: %s", line)
}
}
// Run Files.
for _, fname := range cmd.Files {
if _, err := executeFile(cmd, fname); err != nil {
return errors.Wrapf(err, "executing file: %s", fname)
}
}
return nil
} else if cmd.Config.KafkaConfig != "" {
runner, err := cmd.newKafkaRunner(cmd.Config.KafkaConfig)
if err != nil {
return errors.Wrap(err, "getting new kafka runner")
}
if err := runner.Main.Run(); err != nil {
return errors.Wrap(err, "running kafka")
}
return nil
}
// From this point on, we should be in interactive mode.
// Set up history for saving user input.
cmd.setupHistory()
rl, err := readline.NewEx(&readline.Config{
Prompt: cmd.prompt(false),
HistoryFile: cmd.historyPath,
HistoryLimit: 100000,
DisableAutoSaveHistory: true,
Stdin: cmd.stdin,
Stdout: cmd.stdout,
Stderr: cmd.stderr,
})
if err != nil {
return errors.Wrap(err, "getting readline")
}
defer rl.Close()
// inMidCommand indicates whether a partial command has been received and
// we're still waiting for a termination character.
var inMidCommand bool
for {
rl.SetPrompt(cmd.prompt(inMidCommand))
// Read user provided input.
line, err := rl.Readline()
if err == readline.ErrInterrupt {
inMidCommand = false
cmd.buffer.reset()
continue
} else if err != nil {
return errors.Wrap(err, "reading line")
}
// We append a line feed at the end of each line because at this point
// we have effectively stripped any intentional line feeds (since we are
// reading a line at a time), and we don't want to do that. An example
// of an intentional line feed is in a BULK INSERT CSV STREAM like this
// example:
//
// bulk replace
// into foo (_id, age)
// map (0 id, 1 int)
// from
// x'3,33
// 4,44
// 5,55'
// with
// format 'CSV'
// input 'STREAM';
//
// We want to preserve the line feeds that are contained in the x''
// block; those are intentional as they demarc records within the csv.
qps, mcs, err := cmd.splitter.split(line + "\n")
if err != nil {
cmd.Errorf("error splitting line: %s\n", err)
continue
}
// Save line in the history.
if err := rl.SaveHistory(line); err != nil {
cmd.Errorf("Couldn't save history: %v\n", err)
}
// This is wrapped in an anonymous function so we can capture any
// errors, ignore the rest of the line, and return back to a prompt.
if err := func() error {
for i := range qps {
if qry, err := cmd.buffer.addPart(qps[i]); err != nil {
return errors.Wrap(err, "adding part to buffer")
} else if qry != nil {
if err := cmd.executeAndWriteQuery(qry); err != nil {
return errors.Wrap(err, "executing query")
}
// In addition to saving each line in the history, we also
// save each successful query.
if err := rl.SaveHistory(qry.String() + ";"); err != nil {
cmd.Errorf("Couldn't save query in history: %v\n", err)
}
inMidCommand = false
} else {
inMidCommand = true
}
}
return nil
}(); err != nil {
cmd.Errorf(err.Error() + "\n")
inMidCommand = false
continue
}
// This is wrapped in an anonymous function so we can capture any
// errors, ignore the rest of the line, and return back to a prompt.
if err := func() error {
for i := range mcs {
action, err := mcs[i].execute(cmd)
if err != nil {
return errors.Wrap(err, "executing meta command")
}
switch action {
case actionQuit:
close(cmd.quit)
return nil
case actionReset:
inMidCommand = false
}
}
return nil
}(); err != nil {
cmd.Errorf(err.Error() + "\n")
inMidCommand = false
continue
}
select {
case <-cmd.quit:
if err := cmd.close(); err != nil {
cmd.Errorf("closing: %s\n", err)
}
return nil
default:
// pass
}
}
}
// prompt constructs the prompt that the user sees based on the currently
// connected database and whether the user is in the middle of a sql statement.
func (cmd *Command) prompt(mid bool) string {
db := "fbsql" // default prompt when a database is not set.
if cmd.databaseName != "" {
db = cmd.databaseName
}
if mid {
return strings.Repeat(" ", len(db)) + "-# "
}
return db + "=# "
}
// close is called upon quitting. It should close any remaining open file
// handles used by the CLICommand.
func (cmd *Command) close() error {
return cmd.closeOutput()
}
// setupConfig sets up private struct members based on values provided via the
// configuration flags.
func (cmd *Command) setupConfig() error {
if cmd.Config == nil {
return nil
}
cmd.host = cmd.Config.Host
cmd.port = cmd.Config.Port
cmd.organizationID = cmd.Config.OrganizationID
cmd.database = cmd.Config.Database
cmd.historyPath = cmd.Config.HistoryPath
// Apply any pset flag arguments.
for _, pset := range cmd.Config.PSets {
if err := cmd.applyPSet(pset); err != nil {
return errors.Wrapf(err, "applying pset: %s", pset)
}
}
// If running with the `--csv` flag, configure things to ensure the output
// is correct (i.e. that it's just the csv).
if cmd.Config.CSV {
cmd.writeOptions.format = formatCSV
}
return nil
}
// applyPSet takes a pset string of the form `arg` or `arg=val` and applies it
// as if the user had run `\pset arg val`. The only difference is that applying
// pset here suppresses any output to stdout.
func (cmd *Command) applyPSet(pset string) error {
// We expect arg to be one of the folowing formats:
// arg
// arg=val
args := strings.SplitN(pset, "=", 2)
// This is kind of hacky, but until we re-think the metaCommand interface to
// take a printer interface somewhere (so we can pass in the nopPrinter
// here), we're just going to discard stdout for the duration of this apply,
// and then set stdout back to its previous writer after the apply.
hold := cmd.stdout
cmd.stdout = io.Discard
defer func() {
cmd.stdout = hold
}()
_, err := newMetaPSet(args).execute(cmd)
return err
}
func (cmd *Command) executeAndWriteQuery(qry query) error {
queryResponse, err := cmd.executeQuery(qry)
if err != nil {
if errors.Is(err, ErrOrganizationRequired) {
// Print an error message and return nil, effectively aborting any
// further writes for this query.
cmd.Errorf("Organization required. Use \\org to set an organization.\n")
return nil
}
return errors.Wrap(err, "making query")
}
if err := writeOutput(queryResponse, cmd.writeOptions, cmd.output, cmd.stdout, cmd.stderr); err != nil {
return errors.Wrap(err, "writing out response")
}
return nil
}
func (cmd *Command) executeQuery(qry query) (*featurebase.WireQueryResponse, error) {
wqr, err := cmd.Queryer.Query(cmd.organizationID, cmd.databaseID, qry.Reader())
if err != nil {
return nil, errors.Wrap(err, "executing query")
}
// If we're running in non-interactive mode, we need to check the error that
// comes back in the WireQueryResponse. If there's an error, we want to
// return it now (rather than just printing it later) so that we immediately
// stop any further execution of commands.
if cmd.nonInteractiveMode && wqr.Error != "" {
return nil, errors.Errorf(wqr.Error)
}
return wqr, nil
}
// printer is an interface which encapsulates the methods used to print output
// to the various io.Writers.
type printer interface {
Printf(format string, a ...any)
Outputf(format string, a ...any)
Errorf(format string, a ...any)
}
type nopPrinter struct{}
func newNopPrinter() *nopPrinter {
return &nopPrinter{}
}
func (n *nopPrinter) Printf(format string, a ...any) {}
func (n *nopPrinter) Outputf(format string, a ...any) {}
func (n *nopPrinter) Errorf(format string, a ...any) {}
// Printf is a helper method which sends the given payload to stdout.
func (cmd *Command) Printf(format string, a ...any) {
out := fmt.Sprintf(format, a...)
cmd.stdout.Write([]byte(out))
}
// Outputf is a helper method which sends the given payload to output.
func (cmd *Command) Outputf(format string, a ...any) {
out := fmt.Sprintf(format, a...)
cmd.output.Write([]byte(out))
}
// Errorf is a helper method which sends the given payload to stderr.
func (cmd *Command) Errorf(format string, a ...any) {
out := fmt.Sprintf(format, a...)
cmd.stderr.Write([]byte(out))
}
func (cmd *Command) setupHistory() {
// If HistoryPath has already been configured (i.e. with a command flag),
// don't bother setting up the default in the home directory.
if cmd.historyPath != "" {
return
}
historyPath := ""
if home, err := os.UserHomeDir(); err != nil {
cmd.Errorf("Error getting home directory, command history persistence will be disabled: %v\n", err)
} else {
historyDir := filepath.Join(home, ".featurebase")
err := os.MkdirAll(historyDir, 0o750)
if err != nil {
cmd.Errorf("Creating directory for history: %v\n", err)
} else {
historyPath = filepath.Join(historyDir, "fbsql_history")
}
}
cmd.historyPath = historyPath
}
// printConnInfo displays the currently set host.
// TODO(tlt): extend this to be the output of the /conninfo meta-command.
func (cmd *Command) printConnInfo() {
cmd.Printf("Host: %s\n", hostPort(cmd.host, cmd.port))
}
func (cmd *Command) connectToDatabase(dbName string) error {
var p printer = cmd
if cmd.nonInteractiveMode {
p = newNopPrinter()
}
// Providing a blank ("") or hyphen ("-") dbName is the equivalent of
// disconnecting from the current database. We support the hyphen option
// because calling the `\c` meta-command without an argument is how you
// print the current connection.
switch dbName {
case "-", "":
cmd.databaseID = ""
cmd.databaseName = ""
p.Printf(cmd.connectionMessage())
return nil
}
// Look up dbID based on dbName.
wqr, err := cmd.executeQuery(newRawQuery("SHOW DATABASES"))
if err != nil {
return errors.Wrap(err, "executing query")
}
for _, db := range wqr.Data {
// 0: _id
// 1: name
if db[1] == dbName {
cmd.databaseName = dbName
cmd.databaseID = db[0].(string)
p.Printf(cmd.connectionMessage())
return nil
}
}
return errors.Errorf("invalid database: %s", dbName)
}
func (cmd *Command) orgMessage() string {
if cmd.organizationID == "" {
return "You have not set an organization.\n"
}
return fmt.Sprintf("You have set organization \"%s\".\n", cmd.organizationID)
}
func (cmd *Command) connectionMessage() string {
if cmd.databaseName == "" {
return "You are not connected to a database.\n"
}
return fmt.Sprintf("You are now connected to database \"%s\" (%s).\n", cmd.databaseName, cmd.databaseID)
}
func (cmd *Command) setupClient() error {
// If the Queryer has already been set (in tests for example), don't bother
// trying to detect it.
if cmd.Queryer != nil {
return nil
}
var p printer = cmd
if cmd.nonInteractiveMode {
p = newNopPrinter()
}
if strings.TrimSpace(cmd.host) == "" {
return errors.Errorf("no host provided\n")
}
if !strings.HasPrefix(cmd.host, "http") {
cmd.host = "http://" + cmd.host
}
typ, err := cmd.detectFBType()
if err != nil {
return errors.Wrap(err, "detecting FeatureBase deployment type")
}
switch typ {
case featurebaseTypeOnPremClassic:
p.Printf("Detected on-prem, classic deployment.\n")
cmd.Queryer = &standardQueryer{
Host: cmd.host,
Port: cmd.port,
}
case featurebaseTypeOnPremServerless:
p.Printf("Detected on-prem, serverless deployment.\n")
cmd.Queryer = &serverlessQueryer{
Host: cmd.host,
Port: cmd.port,
}
case featurebaseTypeCloud:
p.Printf("Detected cloud deployment.\n")
cmd.Queryer = &fbcloud.Queryer{
Host: hostPort(cmd.host, cmd.port),
ClientID: cmd.Config.CloudAuth.ClientID,
Region: cmd.Config.CloudAuth.Region,
Email: cmd.Config.CloudAuth.Email,
Password: cmd.Config.CloudAuth.Password,
}
case featurebaseTypeUnknown:
p.Printf("Could not detect deployment\n")
// cmd.Queryer = &nopQueryer{}
// Instead of using a no-op queryer when the type can't be detected, we
// default to using a cloud queryer.
cmd.Queryer = &fbcloud.Queryer{
Host: hostPort(cmd.host, cmd.port),
ClientID: cmd.Config.CloudAuth.ClientID,
Region: cmd.Config.CloudAuth.Region,
Email: cmd.Config.CloudAuth.Email,
Password: cmd.Config.CloudAuth.Password,
}
default:
return errors.Errorf("unknown type: %s", typ)
}
return nil
}
type featurebaseType string
const (
featurebaseTypeUnknown featurebaseType = "unknown" // unknown
featurebaseTypeOnPremClassic featurebaseType = "on-prem-standard" // on-prem, classic
featurebaseTypeOnPremServerless featurebaseType = "on-prem-serverless" // on-prem, serverless
featurebaseTypeCloud featurebaseType = "cloud" // cloud, (both classic and serverless)?
)
func hostPort(host, port string) string {
if port == "" {
return host
}
return host + ":" + port
}
// detectFBType determines if we're talking to standalone FeatureBase
// or FeatureBase Cloud
func (cmd *Command) detectFBType() (featurebaseType, error) {
type trial struct {
port string
health string
typ featurebaseType
}
// trials is populated with the url/endpoints to try in order to detect if a
// process is running there which can support the cli requests.
trials := []trial{}
var clientTimeout time.Duration
if cmd.port != "" {
clientTimeout = 100 * time.Millisecond
trials = append(trials,
// on-prem, serverless
trial{
port: cmd.port,
health: "/queryer/health",
typ: featurebaseTypeOnPremServerless,
},
// on-prem, classic
trial{
port: cmd.port,
health: "/status",
typ: featurebaseTypeOnPremClassic,
},
)
} else if strings.HasPrefix(cmd.host, "https") {
// https suggesting we might be connecting to a cloud host
clientTimeout = 1 * time.Second
trials = append(trials,
// cloud
trial{
port: "",
health: "/health",
typ: featurebaseTypeCloud,
},
)
} else {
// Try default ports just in case.
clientTimeout = 100 * time.Millisecond
trials = append(trials,
// on-prem, serverless
trial{
port: "8080",
health: "/queryer/health",
typ: featurebaseTypeOnPremServerless,
},
// on-prem, classic
trial{
port: "10101",
health: "/status",
typ: featurebaseTypeOnPremClassic,
},
)
}
client := http.Client{
Timeout: clientTimeout,
}
for _, trial := range trials {
url := hostPort(cmd.host, trial.port) + trial.health
if resp, err := client.Get(url); err != nil {
continue
} else if resp.StatusCode/100 == 2 {
cmd.port = trial.port
return trial.typ, nil
}
}
return featurebaseTypeUnknown, nil
}
func (cmd *Command) closeOutput() error {
if cmd.output == nil {
return nil
}
if closer, ok := cmd.output.(io.Closer); ok {
return closer.Close()
}
return nil
}
func (cmd *Command) handleLine(line string) error {
// For single-line command handling, we handle either a meta-command, or
// query parts, but not both. The logic is that any line which begins with
// "\" will be handled as a meta-command, otherwise it will be handled as a
// query.
if len(line) == 0 {
return nil
} else if line[0] == byte('\\') {
return cmd.handleLineAsMetaCommand(line)
} else {
return cmd.handleLineAsQueryParts(line)
}
}
func (cmd *Command) handleLineAsMetaCommand(line string) error {
_, mcs, err := cmd.splitter.split(line)
if err != nil {
return errors.Wrapf(err, "splitting line")
}
for i := range mcs {
_, err := mcs[i].execute(cmd)
if err != nil {
return errors.Wrap(err, "executing meta command")
}
}
return nil
}
func (cmd *Command) handleLineAsQueryParts(line string) error {
qps, mcs, err := cmd.splitter.split(line)
if err != nil {
return errors.Wrapf(err, "splitting line")
} else if len(mcs) > 0 {
return errors.Errorf("--command does not support meta-commands")
}
// Add a termintor part to the end of []queryPart. We do this because the
// command is coming in from the --command flag, it may not end with a
// semi-colon, but we still want to execute it.
if len(qps) > 0 {
if _, ok := qps[len(qps)-1].(*partTerminator); !ok {
qps = append(qps, newPartTerminator())
}
}
for i := range qps {
if qry, err := cmd.buffer.addPart(qps[i]); err != nil {
return errors.Wrap(err, "adding part to buffer")
} else if qry != nil {
if err := cmd.executeAndWriteQuery(qry); err != nil {
return errors.Wrap(err, "executing query")
}
}
}
return nil
}
func (cmd *Command) Insert(sql string) error {
wqr, err := cmd.executeQuery(newRawQuery(sql))
if wqr.Error != "" {
return errors.Errorf(wqr.Error)
}
return err
}

257
cli/cli_integration_test.go Normal file
View file

@ -0,0 +1,257 @@
package cli_test
import (
"bufio"
"context"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/featurebasedb/featurebase/v3/cli"
"github.com/featurebasedb/featurebase/v3/dax/server/test"
"github.com/featurebasedb/featurebase/v3/logger"
"github.com/stretchr/testify/require"
)
func TestCLIIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := context.Background()
t.Run("Stubbed Framework", func(t *testing.T) {
mc := test.MustRunManagedCommand(t)
defer mc.Close()
addr := mc.Address()
capture := newCapture(t)
comparer := newComparer(t)
comparer.run()
fbsql := cli.NewCommand(logger.StderrLogger)
fbsql.SetStdin(capture)
fbsql.SetStdout(comparer)
fbsql.SetStderr(comparer)
fbsql.Config = &cli.Config{
Host: addr.Host(),
Port: fmt.Sprintf("%d", addr.Port()),
}
// Run fbsql in a goroutine so we can continue to send it commands
// below.
didQuit := make(chan struct{})
go func() {
require.NoError(t, fbsql.Run(ctx))
close(didQuit)
}()
// testFiles reference files located in the cli/testdata directory. All
// tests should be placed there; other than adding another test file to
// this list, you probably shouldn't be editing this file unless you are
// trying to modify the way the test framework itself works.
testFiles := []string{
"setup",
"database",
"table",
// the tests below may be dependent on the previous tests, which do
// setup and some shared database and table creation.
"query_buffer",
// meta commands
"meta_bang",
"meta_cd",
"meta_echo",
"meta_describe",
"meta_file",
"meta_pset_border",
"meta_pset_expanded",
"meta_pset_format_csv",
"meta_pset_tuples_only",
"meta_include",
"meta_output",
"meta_set",
"meta_timing",
"meta_write",
}
for _, testFile := range testFiles {
t.Run(testFile, func(t *testing.T) {
f, err := os.Open("testdata/" + testFile)
require.NoError(t, err)
scanner := bufio.NewScanner(f)
var lineNo int
for scanner.Scan() {
line := scanner.Text()
lineNo++
// Empty lines and comments (//) are ignored.
if line == "" {
continue
} else if strings.HasPrefix(line, "//") {
continue
}
parts := strings.SplitN(line, ":", 2)
switch parts[0] {
case "SEND":
v := ""
if len(parts) == 2 {
v = parts[1]
}
capture.sendLine(v)
case "EXPECT":
v := ""
if len(parts) == 2 {
v = parts[1]
}
comparer.expectLine(v, testFile, lineNo)
case "EXPECTCOMP":
if len(parts) == 2 {
comps := strings.SplitN(parts[1], ":", 2)
v := ""
if len(comps) == 2 {
v = comps[1]
}
comparer.expectLineComp(comparator(comps[0]), v, testFile, lineNo)
} else {
t.Errorf("unexpected line: %s[%d]:%s", testFile, lineNo, line)
}
default:
t.Errorf("unexpected line: %s[%d]:%s", testFile, lineNo, line)
}
}
require.NoError(t, scanner.Err())
})
}
// End with quit to ensure that fbsql closes without error.
capture.sendLine(`\q`)
// Ensure fbsql quits cleanly.
select {
case <-didQuit:
case <-time.After(time.Second):
t.Fatalf("expected fbsql to quit")
}
})
}
// compare is used to compare fbsql output written to its Stdout with expected
// lines.
type comparer struct {
t *testing.T
out chan byte
outline chan []byte
exp chan []byte
}
func newComparer(t *testing.T) *comparer {
return &comparer{
t: t,
out: make(chan byte, 1024),
outline: make(chan []byte, 128),
exp: make(chan []byte, 1024),
}
}
func (c *comparer) run() {
// Read bytes off output, and for every line (designated by a line feed "\n"),
// push the line onto the outline channel.
go func() {
var line []byte
for {
b := <-c.out
if b == byte('\n') {
c.outline <- line
line = []byte{}
continue
}
line = append(line, b)
}
}()
}
type comparator string
const (
compEquals = "Equals"
compHasPrefix = "HasPrefix"
compWithFormat = "WithFormat"
)
// expectLine is a convenience method which calls expectLineComp with the compEq
// comparator and the given line.
func (c *comparer) expectLine(line string, fileName string, lineNo int) {
c.expectLineComp(compEquals, line, fileName, lineNo)
}
// expectLineComp reads the next line from the outline channel and compares it
// with the given `line`. A comparator can be provided to inform how the lines
// should be compared (for example, the compHasPrefix comparator will just
// compare the beginning part of the outline).
func (c *comparer) expectLineComp(comp comparator, line string, fileName string, lineNo int) {
var outline []byte
select {
case outline = <-c.outline:
case <-time.After(10 * time.Second):
// TODO(tlt): this is 10 seconds to account for the fb_views creation on
// a local mac. This should really be something like 2 seconds. Put this
// back to 2 once fb_views issue is addressed.
c.t.Fatalf("expected output line %s[%d]: >%s<", fileName, lineNo, line)
}
// msg is included in any require which fails.
msg := []interface{}{"exp: %s[%d], got: >%s<", fileName, lineNo, outline}
switch comp {
case compEquals:
require.Equal(c.t, []byte(line), outline, msg...)
case compHasPrefix:
require.True(c.t, strings.HasPrefix(string(outline), line), msg...)
case compWithFormat:
require.True(c.t, compareByteSlices(outline, []byte(line)), msg...)
default:
c.t.Fatalf("invalid comparator: %s", comp)
}
}
func (c *comparer) Write(b []byte) (n int, err error) {
for i := range b {
c.out <- b[i]
}
return len(b), err
}
// compareByteSlices compares a byte slice s with another byte slice format and
// returns true if they are the same. It will accept underscore as a
// single-character wildcard anywhere in slice format.
func compareByteSlices(s, format []byte) bool {
// Replace some helpers in format before comparing.
f := string(format)
f = strings.ReplaceAll(f, `{uuid}`, `________-____-____-____-____________`)
f = strings.ReplaceAll(f, `{timestamp}`, `____-__-__T__:__:__Z`)
format = []byte(f)
if len(s) != len(format) {
return false
}
for i := range s {
if format[i] == '_' {
continue
}
if s[i] != format[i] {
// log.Printf("DEBUG: characters differ: (%d): '%v' != '%v'", i, s[i], format[i])
return false
}
}
return true
}

199
cli/cli_test.go Normal file
View file

@ -0,0 +1,199 @@
package cli_test
import (
"context"
"io"
"strings"
"sync"
"testing"
"time"
featurebase "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/cli"
"github.com/featurebasedb/featurebase/v3/logger"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestCLI(t *testing.T) {
t.Run("Input", func(t *testing.T) {
ctx := context.Background()
capture := newCapture(t)
cli := cli.NewCommand(logger.StderrLogger)
cli.SetStdin(capture)
cli.SetStdout(capture)
cli.Queryer = capture
go func() {
assert.NoError(t, cli.Run(ctx))
}()
none := []string{}
// One statement, one line.
capture.Assert("one;", []string{"one\n"})
// One statement, multiple lines.
capture.Assert("one", none)
capture.Assert(" two ", none)
capture.Assert("three;", []string{"one\ntwo\nthree\n"})
// Multiple statements, one line.
capture.Assert("foo; bar;", []string{"foo\n", "bar\n"})
// Multiple statements, multiple lines.
capture.Assert("a1", none)
capture.Assert("a2; b1", []string{"a1\na2\n"})
capture.Assert("b2;", []string{"b1\nb2\n"})
// Blank lines.
capture.Assert("one", none)
capture.Assert("", none)
capture.Assert("three;", []string{"one\nthree\n"})
// Just a semi-colon.
capture.Assert(";", []string{""})
// Multi-line with just a semi-colon.
capture.Assert("one", none)
capture.Assert(";", []string{"one\n"})
// Ensure a clean exit with no errors.
assert.NoError(t, capture.Exit())
})
}
////////////////////////////////////////////////////////
// Ensure type implementes interface.
var _ io.ReadCloser = (*capture)(nil)
var _ io.Writer = (*capture)(nil)
var _ cli.Queryer = (*capture)(nil)
// capture implements the various CLI interfaces in order to capture test input
// and submit it as though that input were being read from the command line. It
// also captures calls made to the Queryer.Query method and ensures the sql they
// contain is expected.
type capture struct {
t *testing.T
// ch is a channel of strings (one line at a time) of CLI input.
ch chan string
mu sync.RWMutex
sqls []string
// queryDone will receive an event any time the Query method is called and
// has completed. This is to tell the Assert method that it's safe to
// compare the sqls slice.
queryDone chan struct{}
asserting chan struct{}
err error
}
func newCapture(t *testing.T) *capture {
return &capture{
t: t,
ch: make(chan string),
sqls: make([]string, 0),
queryDone: make(chan struct{}),
}
}
func (c *capture) Exit() error {
c.sendLine(`\q`)
c.mu.RLock()
defer c.mu.RUnlock()
return c.err
}
func (c *capture) Assert(in string, out []string) {
c.asserting = make(chan struct{})
c.sendLine(in)
// Wait for the CLI command to complete processing the input and send the
// sql to Query() by blocking on the queryDone channel. Because Query gets
// called for every sql statement in the input, an input resulting in
// multiple sql statements needs to wait for all expected queries to
// complete. A timeout is included to this so it doesn't deadlock in the
// case where Query is expected to be called, but isn't; after the timeout,
// the test should fail completely. In summary: we wait on queryDone the
// number of sql statements we expect. If we receive fewer than expected,
// the timeout will occur. If we receive more than expected, the Query()
// method will effectively deadlock, reach its own timout, then write to
// capture.err, which will be reported upon Exit().
for range out {
select {
case <-c.queryDone:
case <-time.After(2 * time.Second):
c.t.Fatalf("expected Query() to be called")
}
}
close(c.asserting)
c.mu.Lock()
defer c.mu.Unlock()
assert.Equal(c.t, out, c.sqls)
// Reset the slice.
c.sqls = c.sqls[:0]
}
// sendLine sends the given string as a line input to the CLI command. It
// appends a line feed to the end of string in order to mimic the user hitting
// the return key.
func (c *capture) sendLine(s string) {
// Add a line feed before putting s on the channel in order to mimic the
// user hitting the return key.
c.ch <- s + "\n"
}
// Read is read by the CLI in place of user input. It effectively sends lines of
// input to the CLI, getting each line to be sent off the channel.
func (c *capture) Read(b []byte) (n int, err error) {
s := <-c.ch
return strings.NewReader(s).Read(b)
}
func (c *capture) Close() error {
close(c.ch)
return nil
}
// Write is called with anything written to output. This would included results
// from calling Query() under normal, non-testing conditions, as well as other
// informational text sent to output, such as the splash message.
func (c *capture) Write(b []byte) (n int, err error) {
return 0, nil
}
// Query is called by the CLI command once a full SQL statement is received
// (signified by the terminator: `;`).
func (c *capture) Query(org string, db string, sql io.Reader) (*featurebase.WireQueryResponse, error) {
tmpBuf := new(strings.Builder)
_, err := io.Copy(tmpBuf, sql)
if err != nil {
return nil, err
}
c.mu.Lock()
c.sqls = append(c.sqls, tmpBuf.String())
c.mu.Unlock()
select {
case c.queryDone <- struct{}{}:
case <-c.asserting:
c.mu.Lock()
c.err = errors.Errorf("unexpected query: %s", sql)
c.mu.Unlock()
}
return &featurebase.WireQueryResponse{}, nil
}

31
cli/config.go Normal file
View file

@ -0,0 +1,31 @@
package cli
// Config represents the configuration for the command.
type Config struct {
Host string `json:"host"`
Port string `json:"port"`
OrganizationID string `json:"org-id"`
Database string `json:"db"`
// CloudAuth
CloudAuth CloudAuthConfig `json:"cloud-auth"`
// Kafka
KafkaConfig string `json:"kafka-config"`
HistoryPath string `json:"history-path"`
// CSV (Comma-Separated Values) table output mode.
CSV bool `json:"csv"`
// PSet takes one or more pset arguments of the form: `--pset=VAR[=ARG]`.
PSets []string `json:"pset"`
}
type CloudAuthConfig struct {
ClientID string `json:"client-id"`
Region string `json:"region"`
Email string `json:"email"`
Password string `json:"password"`
}

16
cli/errors.go Normal file
View file

@ -0,0 +1,16 @@
package cli
import (
"github.com/featurebasedb/featurebase/v3/errors"
)
const (
ErrOrganizationRequired errors.Code = "OrganizationRequired"
)
func NewErrOrganizationRequired() error {
return errors.New(
ErrOrganizationRequired,
"organization required",
)
}

79
cli/fbcloud/auth.go Normal file
View file

@ -0,0 +1,79 @@
package fbcloud
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/pkg/errors"
)
const (
authFlow = "USER_PASSWORD_AUTH"
cognitoURLTemplate = "https://cognito-idp.%s.amazonaws.com"
)
type cognitoParameters struct {
Email string `json:"USERNAME"`
Password string `json:"PASSWORD"`
}
type cognitoAuthRequest struct {
AuthParameters cognitoParameters `json:"AuthParameters"`
AuthFlow string `json:"AuthFlow"`
AppClientID string `json:"ClientId"`
}
type cognitoAuthResult struct {
IDToken string `json:"IdToken"`
}
type cognitoAuthResponse struct {
Result cognitoAuthResult `json:"AuthenticationResult"`
}
func authenticate(clientID, region, email, password string) (string, error) {
authPayload := cognitoAuthRequest{
AuthParameters: cognitoParameters{
Email: email,
Password: password,
},
AuthFlow: authFlow,
AppClientID: clientID,
}
data, err := json.Marshal(authPayload)
if err != nil {
return "", errors.Wrap(err, "marshaling json")
}
url := fmt.Sprintf(cognitoURLTemplate, region)
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))
if err != nil {
return "", errors.Wrap(err, "creating authentication request object")
}
req.Header.Add("Content-Type", "application/x-amz-json-1.1")
req.Header.Add("X-Amz-Target", "AWSCognitoIdentityProviderService.InitiateAuth")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", errors.Wrap(err, "making request")
}
defer resp.Body.Close()
fullbod, err := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK || err != nil {
return "", errors.Errorf("HTTP status code=%d from Cognito authentication response. reading body: %v, body: '%s'", resp.StatusCode, err, fullbod)
}
var auth cognitoAuthResponse
err = json.Unmarshal(fullbod, &auth)
if err != nil {
return "", errors.Wrap(err, "decoding cognito auth response")
}
return auth.Result.IDToken, nil
}

131
cli/fbcloud/client.go Normal file
View file

@ -0,0 +1,131 @@
package fbcloud
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
featurebase "github.com/featurebasedb/featurebase/v3"
"github.com/pkg/errors"
)
// TokenRefreshTimeout is currently hardcoded to be just under the
// Cognito token timeout for cloud which is 15 minutes (I think I
// heard that somewhere anyway). It seems to work.
const TokenRefreshTimeout = time.Minute * 13
type Queryer struct {
Host string
ClientID string
Region string
Email string
Password string
token string
lastRefresh time.Time
}
func (cq *Queryer) tokenRefresh() error {
token, err := authenticate(cq.ClientID, cq.Region, cq.Email, cq.Password)
if err != nil {
return errors.Wrap(err, "getting token")
}
cq.token = token
cq.lastRefresh = time.Now()
return nil
}
// Query issues a SQL query formatted for the FeatureBase cloud query endpoint.
func (cq *Queryer) Query(org string, db string, sql io.Reader) (*featurebase.WireQueryResponse, error) {
if time.Since(cq.lastRefresh) > TokenRefreshTimeout {
if err := cq.tokenRefresh(); err != nil {
return nil, errors.Wrap(err, "refreshing token")
}
}
url := fmt.Sprintf("%s/databases/%s/sql", cq.Host, db)
if db == "" {
url = fmt.Sprintf("%s/sql", cq.Host)
}
client := &http.Client{
Timeout: time.Second * 30,
}
req, err := http.NewRequest(http.MethodPost, url, sql)
if err != nil {
return nil, errors.Wrap(err, "creating new post request")
}
req.Header.Add("Content-Type", "text/plain")
req.Header.Add("Authorization", cq.token)
var resp *http.Response
if resp, err = client.Do(req); err != nil {
return nil, errors.Wrap(err, "executing post request")
}
fullbod, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "reading cloud response")
}
if resp.StatusCode/100 != 2 {
return nil, errors.Errorf("unexpected status: %s, full body: '%s'", resp.Status, fullbod)
}
var sqlResponse featurebase.WireQueryResponse
if err := json.Unmarshal(fullbod, &sqlResponse); err != nil {
return nil, errors.Wrapf(err, "decoding cloud response, body:\n%s", fullbod)
}
return &sqlResponse, nil
}
// HTTPRequest can make an arbitrary http request to the host and
// tries to json unmarshal the response body into v if v is
// non-nil. This is handy for hitting cloud endpoints other than the
// query endpoint which is handled by Query. I don't think this is
// currently used, but I'd like to keep it around for debugging.
func (cq *Queryer) HTTPRequest(method, path, body string, v interface{}) ([]byte, error) {
if time.Since(cq.lastRefresh) > TokenRefreshTimeout {
if err := cq.tokenRefresh(); err != nil {
return nil, errors.Wrap(err, "refreshing token")
}
}
var bod io.Reader
if body == "" {
bod = nil
} else {
bod = strings.NewReader(body)
}
req, err := http.NewRequest(method, fmt.Sprintf("%s%s", cq.Host, path), bod)
if err != nil {
return nil, errors.Errorf("creating request: %v", err)
}
// fmt.Printf("%+v\n", req)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", cq.token))
if bod != nil {
req.Header.Add("Content-Type", "application/json")
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, errors.Errorf("doing request: %v", err)
}
bodbytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Errorf("reading response body: %v", err)
}
if resp.StatusCode/100 != 2 {
return nil, errors.Errorf("bad status: %s. body: '%s'", resp.Status, bodbytes)
}
if v != nil {
err = json.Unmarshal(bodbytes, v)
if err != nil {
return nil, errors.Errorf("unmarshaling: %v", err)
}
}
return bodbytes, nil
}

70
cli/kafka.go Normal file
View file

@ -0,0 +1,70 @@
package cli
import (
"fmt"
"github.com/featurebasedb/featurebase/v3/cli/batch"
"github.com/featurebasedb/featurebase/v3/cli/kafka"
"github.com/featurebasedb/featurebase/v3/errors"
"github.com/spf13/viper"
)
func (cmd *Command) newKafkaRunner(cfgFile string) (*kafka.Runner, error) {
// Read the kafka config file.
v := viper.New()
v.SetConfigFile(cfgFile)
v.SetConfigType("toml")
err := v.ReadInConfig()
if err != nil {
return nil, fmt.Errorf("error reading configuration file '%s': %v", cfgFile, err)
}
cfg := kafka.Config{}
if err := v.Unmarshal(&cfg); err != nil {
return nil, errors.Wrap(err, "unmarshalling config")
}
if err := kafka.ValidateConfig(cfg); err != nil {
return nil, errors.Wrap(err, "validating config")
}
// Create a new config with defaults.
// Look up fields based on table provided in the config.
wqr, err := cmd.executeQuery(newRawQuery("SHOW COLUMNS FROM " + cfg.Table))
if err != nil {
return nil, errors.Wrap(err, "executing query")
}
scr, err := wqr.ShowColumnsResponse()
if err != nil {
return nil, errors.Wrap(err, "getting show columns from wire query response")
}
// If no fields were provided in the config, use the fields defined on the
// table and assume a 1-to-1 mapping of source to destination.
if len(cfg.Fields) == 0 {
cfg.Fields = kafka.FieldsToConfig(scr.Fields)
} else {
cfg.Fields, err = kafka.CheckFieldCompatibility(cfg.Fields, scr)
if err != nil {
return nil, errors.Wrap(err, "validating config fields")
}
}
idkCfg, err := kafka.ConvertConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "cleaning config")
}
flds, err := kafka.ConfigToFields(cfg)
if err != nil {
return nil, errors.Wrap(err, "getting fields from config")
}
return kafka.NewRunner(
idkCfg,
batch.NewSQLBatcher(cmd, flds),
cmd.stderr,
), nil
}

251
cli/kafka/config.go Normal file
View file

@ -0,0 +1,251 @@
package kafka
import (
"fmt"
"time"
featurebase "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/dax"
"github.com/featurebasedb/featurebase/v3/idk"
"github.com/pkg/errors"
)
// Config is the user-facing configuration for kafka support in the CLI. This is
// unmarshalled from the the toml config file supplied by the user.
type Config struct {
Hosts []string `mapstructure:"hosts" help:"Kafka hosts."`
Group string `mapstructure:"group" help:"Kafka group."`
Topics []string `mapstructure:"topics" help:"Kafka topics to read from."`
BatchSize int `mapstructure:"batch-size" help:"Batch size."`
BatchMaxStaleness time.Duration `mapstructure:"batch-max-staleness" help:"Maximum length of time that the oldest record in a batch can exist before flushing the batch. Note that this can potentially stack with timeouts waiting for the source."`
Timeout time.Duration `mapstructure:"timeout" help:"Time to wait for more records from Kafka before flushing a batch. 0 to disable."`
Table string `mapstructure:"table" help:"Destination table name."`
Fields []Field `mapstructure:"fields"`
}
// Field is a user-facing configuration field.
type Field struct {
Name string `mapstructure:"name"`
SourceType string `mapstructure:"source-type"`
SourcePath []string `mapstructure:"source-path"`
PrimaryKey bool `mapstructure:"primary-key"`
}
// ConfigForIDK represents Config converted to values suitable for IDK. In
// particular, the idk.RawField is used in parsing the schema in IDK.
type ConfigForIDK struct {
Hosts []string
Group string
Topics []string
BatchSize int
BatchMaxStaleness time.Duration
Timeout time.Duration
Table string
IDField string
Fields []idk.RawField
}
// ValidateConfig validates the config is usable.
func ValidateConfig(c Config) error {
if c.Table == "" {
return errors.Errorf("table is required")
} else if len(c.Topics) == 0 {
return errors.Errorf("at least one topic is required")
} else if len(c.Fields) > 0 {
// We only need to do these checks if any fields are specified at all.
// If no fields are specified, that's ok because then we default to
// using fields based off the existing table.
if len(c.Fields) < 2 {
return errors.Errorf("at least two fields are required (one should be a primary key)")
} else {
var found int
for i := range c.Fields {
if c.Fields[i].PrimaryKey {
found++
}
if c.Fields[i].Name == "" {
return errors.Errorf("a name attribute (which isn't equal to \"\") should exist for all fields")
}
}
if found != 1 {
return errors.Errorf("exactly one primary key field is required")
}
}
}
return nil
}
// ConvertConfig converts a Config to one that suitable for IDK.
func ConvertConfig(c Config) (ConfigForIDK, error) {
// Set a default kafka host in case one isn't provided.
hosts := []string{"localhost:9092"}
if len(c.Hosts) > 0 {
hosts = c.Hosts
}
// Copy all the shared members from Config to ConfigForIDK.
out := ConfigForIDK{
Hosts: hosts,
Group: c.Group,
Topics: c.Topics,
BatchSize: c.BatchSize,
BatchMaxStaleness: c.BatchMaxStaleness,
Timeout: c.Timeout,
Table: c.Table,
}
if len(c.Fields) == 0 {
return out, errors.New("fields cannot be empty")
}
// rawFields wil be the same as c.Fields, but possibly enhanced.
rawFields := make([]idk.RawField, 0, len(c.Fields))
var foundPK bool
for _, fld := range c.Fields {
if fld.PrimaryKey {
out.IDField = fld.Name
foundPK = true
}
typ, quals, err := dax.SplitFieldType(fld.SourceType)
if err != nil {
return out, errors.Wrap(err, "getting base type")
}
rawFld := idk.RawField{
Name: fld.Name,
Type: string(typ),
Path: fld.SourcePath,
}
// If a SourcePath wasn't provided, default to using the field name.
if len(rawFld.Path) == 0 {
rawFld.Path = []string{fld.Name}
}
switch typ {
case dax.BaseTypeInt:
// We don't have to handle min/max because we don't create the table.
case dax.BaseTypeDecimal:
if len(quals) != 1 {
return out, errors.Errorf("expected decimal scale")
}
rawFld.Config = []byte(fmt.Sprintf(`{"scale":%d}`, quals[0]))
case dax.BaseTypeID:
rawFld.Config = []byte("{\"mutex\":true}")
case dax.BaseTypeIDSet:
rawFld.Type = "ids"
case dax.BaseTypeString:
rawFld.Config = []byte("{\"mutex\":true}")
case dax.BaseTypeStringSet:
rawFld.Type = "strings"
case dax.BaseTypeTimestamp:
// No timestamp options are handled for now.
}
rawFields = append(rawFields, rawFld)
}
if !foundPK {
return out, errors.New("primary-key not found in fields")
}
out.Fields = rawFields
return out, nil
}
// ConfigToFields returns a list of *dax.Field based on the IDField and Fields
// in the Config.
func ConfigToFields(c Config) ([]*dax.Field, error) {
// We don't know if a primary key will be found, so we can't set the
// capacity to `len(c.Fields)-1`.
out := make([]*dax.Field, 0, len(c.Fields))
for _, fld := range c.Fields {
if fld.PrimaryKey {
continue
}
typ, quals, err := dax.SplitFieldType(fld.SourceType)
if err != nil {
return nil, errors.Wrap(err, "splitting field type")
}
dfld := &dax.Field{
Name: dax.FieldName(fld.Name),
Type: typ,
}
switch typ {
case dax.BaseTypeDecimal:
if len(quals) != 1 {
return nil, errors.Errorf("expected decimal scale")
}
scale, ok := quals[0].(int64)
if !ok {
return nil, errors.Errorf("invalid decimal scale: %v", quals[0])
}
dfld.Options.Scale = scale
}
out = append(out, dfld)
}
return out, nil
}
// FieldsToConfig returns a Config.Fields based on a list of *dax.Field.
func FieldsToConfig(flds []*dax.Field) []Field {
out := make([]Field, 0, len(flds))
for _, fld := range flds {
out = append(out, Field{
Name: string(fld.Name),
SourceType: fld.FullType(),
PrimaryKey: fld.IsPrimaryKey(),
})
}
return out
}
// CheckFieldCompatibility ensures that the fields provided in the kafka config
// are compatible with the fields in the existing table. It returns a copy of
// the kafka config fields with empty values defaulted to the table field
// configuration.
func CheckFieldCompatibility(cflds []Field, scr *featurebase.ShowColumnsResponse) ([]Field, error) {
out := make([]Field, len(cflds))
for i, cfld := range cflds {
out[i] = cfld
cfldName := dax.FieldName(cfld.Name)
// Primary key field.
if cfld.PrimaryKey {
f := scr.Field(dax.PrimaryKeyFieldName)
if f == nil {
return nil, dax.NewErrFieldDoesNotExist(dax.PrimaryKeyFieldName) // It should be impossible to hit this.
}
if out[i].SourceType == "" {
if f.StringKeys() {
out[i].SourceType = dax.BaseTypeString
} else {
out[i].SourceType = dax.BaseTypeID
}
}
continue
}
// Non primary key fields.
if cfldName == dax.PrimaryKeyFieldName {
return nil, errors.Errorf("field named '%s' must be a primary key", dax.PrimaryKeyFieldName)
}
f := scr.Field(cfldName)
if f == nil {
return nil, dax.NewErrFieldDoesNotExist(cfldName)
}
if out[i].SourceType == "" {
out[i].SourceType = f.FullType()
}
}
return out, nil
}

67
cli/kafka/runner.go Normal file
View file

@ -0,0 +1,67 @@
package kafka
import (
"io"
"time"
fbbatch "github.com/featurebasedb/featurebase/v3/batch"
"github.com/featurebasedb/featurebase/v3/errors"
"github.com/featurebasedb/featurebase/v3/idk"
"github.com/featurebasedb/featurebase/v3/idk/kafka_static"
"github.com/featurebasedb/featurebase/v3/logger"
)
// Runner is a CLI-specific kafka consumer. It's similar to
// idk.kafka_static.Main in that it embeds idk.Main and contains additional
// functionality specific to its use case.
type Runner struct {
idk.Main `flag:"!embed"`
KafkaHosts []string `help:"Comma separated list of host:port pairs for Kafka."`
Group string `help:"Kafka group."`
Topics []string `help:"Kafka topics to read from."`
Timeout time.Duration `help:"Time to wait for more records from Kafka before flushing a batch. 0 to disable."`
Header []idk.RawField `help:"Header configuration."`
}
func NewRunner(cfg ConfigForIDK, batcher fbbatch.Batcher, logWriter io.Writer) *Runner {
idkMain := idk.NewMain()
idkMain.IDField = cfg.IDField
idkMain.Index = cfg.Table
idkMain.Batcher = batcher
idkMain.BatchSize = cfg.BatchSize
idkMain.BatchMaxStaleness = cfg.BatchMaxStaleness
idkMain.SetBasic()
idkMain.SetLog(logger.NewStandardLogger(logWriter))
kr := &Runner{
Main: *idkMain,
KafkaHosts: cfg.Hosts,
Group: cfg.Group,
Topics: cfg.Topics,
Header: cfg.Fields,
Timeout: cfg.Timeout,
}
kr.OffsetMode = true
kr.Main.Namespace = "cli_kafka_runner"
kr.Main.Pprof = "" // don't initialize pprof until we actually use it in tests
kr.NewSource = func() (idk.Source, error) {
source := kafka_static.NewSource()
source.Hosts = kr.KafkaHosts
source.Group = kr.Group
source.Topics = kr.Topics
source.Log = kr.Main.Log()
// source.TLS = m.KafkaTLS
source.Timeout = kr.Timeout
// source.SkipOld = m.SkipOld
source.HeaderFields = kr.Header
// source.S3Region = m.S3Region
// source.AllowMissingFields = m.AllowMissingFields
err := source.Open()
if err != nil {
return nil, errors.Wrap(err, "opening source")
}
return source, nil
}
return kr
}

1166
cli/meta.go Normal file

File diff suppressed because it is too large Load diff

136
cli/parts.go Normal file
View file

@ -0,0 +1,136 @@
package cli
import (
"fmt"
"io"
"os"
"strings"
)
// query is a collection of queryParts which, when applied together, make up an
// executable SQL query.
type query []queryPart
func (q query) String() string {
var sb strings.Builder
for i := range q {
sb.WriteString(q[i].String())
if i < len(q)-1 {
sb.WriteRune('\n')
}
}
return sb.String()
}
// Reader returns the query as an io.Reader so that it can be passed to, for
// example, http.Post().
func (q query) Reader() io.Reader {
readers := make([]io.Reader, 0, len(q))
for i := range q {
readers = append(readers, q[i].Reader())
}
return io.MultiReader(readers...)
}
// queryPart is an interface representing anything which can use to build up a
// query.
type queryPart interface {
fmt.Stringer
Reader() io.Reader
}
func newRawQuery(s string) query {
return []queryPart{
newPartRaw(s),
}
}
// ////////////////////////////////////////////////////////////////////////////
// raw
// ////////////////////////////////////////////////////////////////////////////
// Ensure type implements interface.
var _ queryPart = (*partRaw)(nil)
type partRaw struct {
raw string
}
func newPartRaw(s string) *partRaw {
return &partRaw{
raw: s,
}
}
func (p *partRaw) Reader() io.Reader {
return strings.NewReader(p.raw + "\n")
}
func (p *partRaw) String() string {
return p.raw
}
// ////////////////////////////////////////////////////////////////////////////
// file
// ////////////////////////////////////////////////////////////////////////////
// Ensure type implements interface.
var _ queryPart = (*partFile)(nil)
type partFile struct {
file *os.File
}
func newPartFile(f *os.File) *partFile {
return &partFile{
file: f,
}
}
func (p *partFile) Reader() io.Reader {
return p.file
}
func (p *partFile) String() string {
return fmt.Sprintf("[file: %s]", p.file.Name())
}
// ////////////////////////////////////////////////////////////////////////////
// batch file
// ////////////////////////////////////////////////////////////////////////////
// Ensure type implements interface.
var _ queryPart = (*partBatchFile)(nil)
type partBatchFile struct {
file *os.File
}
func (p *partBatchFile) Reader() io.Reader {
return p.file
}
func (p *partBatchFile) String() string {
return p.file.Name()
}
// ////////////////////////////////////////////////////////////////////////////
// terminator (i.e. ";")
// ////////////////////////////////////////////////////////////////////////////
// Ensure type implements interface.
var _ queryPart = (*partTerminator)(nil)
type partTerminator struct{}
func newPartTerminator() *partTerminator {
return &partTerminator{}
}
func (p *partTerminator) Reader() io.Reader {
return nil
}
func (p *partTerminator) String() string {
return terminationChar
}

Some files were not shown because too many files have changed in this diff Show more