Compare commits

...

3823 commits

Author SHA1 Message Date
Matthew Jaffee
c4af73e081 fix tag check to check against null
empty string doesn't work because gitlab doesn't set the variable at
all. How do I know that "null" is correct? Because Fletcher told
me... apparently it's a ruby-ism
2022-02-16 08:29:19 -06:00
Matthew Jaffee
504fce8e4d fix up S3 release dump
- remove commit SHA nesting
- add NOTICE, .service files, and .conf
2022-02-16 08:29:19 -06:00
Matthew Jaffee
1433d9ce83 add separate S3 dump step for tags 2022-02-16 08:29:14 -06:00
Ben Johnson
b570a38780
Merge pull request #1925 from molecula/rank-cache-bulk-invalidation
[FB-1206] Periodically invalidate rank cache during bulk add
2022-02-15 10:34:22 -07:00
Ben Johnson
6b84d685d5 Periodically invalidate rank cache during bulk add
This commit changes `RankCache.BulkAdd()` so that entries are
limited to an upper bound of 2x `maxEntries`. When this bound
is exceeded then the cache is automatically recalculated.
2022-02-15 08:25:45 -07:00
Matthew Jaffee
6e41c663e0
Merge pull request #1923 from molecula/cicd-will-it-never-end
Cicd will it never end
2022-02-15 08:43:53 -06:00
pokeeffe-molecula
fdb500898d fixed path 2022-02-15 07:59:33 -06:00
pokeeffe-molecula
355b522dac
Merge branch 'master' into cicd-will-it-never-end 2022-02-14 17:22:12 -06:00
pokeeffe-molecula
f97878edcf fixed arch problem 2022-02-14 16:31:55 -06:00
hphamMolecula
d1c2861469
Merge pull request #1922 from molecula/sup-145
SUP-145: Removed shard list in "shard unavailable" error log
2022-02-14 16:04:27 -06:00
hphamMolecula
38fc2f9dbb
Merge branch 'master' into sup-145 2022-02-14 15:25:18 -06:00
tgruben
d75e6888fc
Merge pull request #1918 from molecula/sup-146
[SUP-146] roaring-migrate bug;performance improvements
2022-02-14 15:08:26 -06:00
Todd Gruben
6c512359a1 missed a fmt statement 2022-02-14 14:53:47 -06:00
Todd Gruben
cbc9bf71a1 logging 2022-02-14 14:41:22 -06:00
hphamMolecula
8f1349543f
Merge branch 'master' into sup-145 2022-02-14 14:40:12 -06:00
Todd Gruben
d4b7d0cb57 Merge branch 'sup-146' of github.com:molecula/featurebase into sup-146 2022-02-14 14:09:13 -06:00
Todd Gruben
8a48c1b67a standard logger 2022-02-14 14:09:05 -06:00
tgruben
baa3a7793f
Merge branch 'master' into sup-146 2022-02-14 13:47:00 -06:00
Kasey C. Rodgers
956c37ec85
Merge pull request #1919 from molecula/fb1163-etcd-source-of-truth
make etcd schema primary source of truth for indexes and fields
2022-02-14 11:01:55 -08:00
tgruben
33451254e6
Merge branch 'master' into sup-146 2022-02-14 12:28:20 -06:00
Kasey C. Rodgers
ede8cf61a0
Merge branch 'master' into fb1163-etcd-source-of-truth 2022-02-14 10:28:10 -08:00
tgruben
c4eebc6885
Update cmd/roaring-migrate/main.go
Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2022-02-14 12:17:55 -06:00
tgruben
89598a7788
Update cmd/roaring-migrate/main.go
Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2022-02-14 12:17:42 -06:00
tgruben
e1e968ef97
Update cmd/roaring-migrate/main.go
Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2022-02-14 12:17:24 -06:00
Todd Gruben
7e25ca467a Merge branch 'sup-146' of github.com:molecula/featurebase into sup-146 2022-02-14 12:12:30 -06:00
Todd Gruben
9bc28091c9 better testing 2022-02-14 12:11:28 -06:00
kcrodgers24
d57050d966 requested idx == nil fix; add doc comment 2022-02-14 10:09:33 -08:00
seebs
a98546c086
Merge pull request #1906 from molecula/task
improve task pool and give it some testing
2022-02-14 11:34:34 -06:00
kcrodgers24
7013910158 give each test its own InMemSchemator 2022-02-14 09:15:23 -08:00
pokeeffe-molecula
f35741adcf removing experiments 2022-02-14 10:46:58 -06:00
Hoang Pham
63b5eed010 SUP-145: Removed shard list in "shard unavailable" error log 2022-02-14 10:10:04 -06:00
Seebs
96ab9314d1 use task pool for executor workers
This adopts the task pool functionality to let us spawn new worker
threads when worker threads are blocked. The underlying reason for
this is the same as the reason for the previous worker-pool-growing
strategy; while our design persistently has at least one thing which
can proceed, it can be the case that there are N things blocked,
where N is the size of our worker pool. Blocked workers shouldn't
count against our desired number of workers.

Originally, the intent was to thread this into RBF, and provide
backpressure from RBF on the pool when blocking on writes. Unfortunately,
that's not good enough, because while a write is blocked, the Qcx
calling it is *also* holding the Qcx's mutex, which means that any other
NewTx on that Qcx will *also* block. So we need to block for the
entire time of the NewTx.

Removing the existing worker spawning code resulted in a subtle
and maybe-harmless change; prior to this, each invocation of `mapperLocal`
would hold a lock, which meant that all the tasks for a given local mapper
would be put in the queue *sequentially*, ensuring that they'd all be
picked up by workers before things from later workers.

With the new pushback, that's not, strictly, necessary. Also, if you
disable it, you can end up with 300,000 goroutines at once, most of them
blocked.

A smallish run does, in fact, eventually complete anyway -- it will
indeed keep making workers until everything gets one. However, while
it's *correct*, it's also noticably *slower*. The same test workload
goes from around 33 seconds to a bit over 40 seconds when that lock
isn't present. (But that's with an extremely small WAL write cap
introduced to make the previous deadlock possible.)

With large numbers of shards, the practical impact is that you can
have quite a lot of things in process, with hundreds of goroutines
each, all blocked waiting for one writer. If we force them to all be
processed at the same time, all the reads that are connected to
each other are much more likely to get all processed at once, before
something new comes along.

In short, that lock isn't strictly necessary but it seems to help
noticably with performance and reduce simultaneous goroutines
significantly.
2022-02-14 09:56:20 -06:00
Seebs
ff091b0346 implement a task pool
This implements a task pool which can handle backpressure; the
idea is, you have a target number of workers, but when a worker
blocks, you can tell it that it's blocking, and it can spawn
another worker in the mean time. This reduces the bounding provided
by the worker pool, and can significantly overshoot the intended size
of the pool in some cases, but it provides quick scaling up when
part of a workload gets blocked.

There's also a simulator attached to it. The simulator's job is
to act similarly to the executor's worker pool working on RBF
databases, including the weird semantics of writes and reads;
specifically, that reads aren't blocked by writes, but a write
can't terminate until every read that started before it has exited.
(This is an oversimplification; actually, writes can complete,
but they still hold the write lock until any WAL merge completes,
and the WAL merge can't complete until old reads are done.)

The simulator is significantly more complicated than the pool.
2022-02-14 09:56:19 -06:00
tgruben
e963bccc93
Merge branch 'master' into sup-146 2022-02-14 08:16:37 -06:00
pokeeffe-molecula
6362173288 testing a theory 2022-02-12 11:30:04 -06:00
pokeeffe-molecula
06e70d41e9 added a job to clean up files 2022-02-12 11:22:03 -06:00
pokeeffe-molecula
03da38d677 Merge branch 'master' into cicd-will-it-never-end 2022-02-12 11:14:26 -06:00
pokeeffe-molecula
4d8ff30eaa Merge branch 'master' into cicd-will-it-never-end 2022-02-11 17:33:13 -06:00
Matthew Jaffee
40eff84e25
Merge pull request #1920 from molecula/coverage-permission-denied
try to clean up some files that are causing CI heartburn
2022-02-11 17:32:55 -06:00
Matthew Jaffee
490ad7f08a try to clean up some files that are causing CI heartburn 2022-02-11 16:59:11 -06:00
pokeeffe-molecula
92d491682d added perf test 2022-02-11 15:38:33 -06:00
Matthew Jaffee
7a0025f417
Merge pull request #1911 from molecula/max-memory-extract-only
[SUP-143] Restrict max-memory setting to Extract() only
2022-02-11 14:47:24 -06:00
Ben Johnson
6d06f5550b Restrict max-memory to Extract() calls only 2022-02-11 14:19:56 -06:00
Matthew Jaffee
4fb22e495c
Merge pull request #1916 from molecula/test-port-conflicts
more binding to 0==less port conflicts in CI
2022-02-11 14:04:52 -06:00
kcrodgers24
4e7c72cc00 make etcd schema primary source of truth for indexes and fields 2022-02-11 11:47:49 -08:00
Matthew Jaffee
b5dae698ff remove unused env var from test
cluster.hosts is no longer a config option since move to etcd
2022-02-11 12:02:10 -06:00
Matthew Jaffee
53a33134d9 add verbose output to race tests 2022-02-11 12:02:10 -06:00
Matthew Jaffee
102a6e723b more binding to 0==less port conflicts in CI 2022-02-11 12:02:10 -06:00
souhailanoor
7a2929d788
Merge pull request #1913 from molecula/clustertests-coverage
FB-1183: Enable code coverage for clustertests
2022-02-11 11:50:36 -06:00
pokeeffe-molecula
23980af634 Merge branch 'master' into cicd-will-it-never-end 2022-02-11 11:40:11 -06:00
Souhaila Noor
7983a7506f - Need to get code coverage on the server and client side
- For server side, used an instrumented binary with a test that wraps around the main entrypoint for featurebase
- Every time, the binary is called, a new coverage file is generated.
- For the client side, used the standard -coverprofile flag for go test to generate code coverage
- For backup test that's expected to fail, needed to call Run call in backup.go directly. The code coverage is not written to disk for an instrumented binary if there is an error.
2022-02-11 11:26:00 -06:00
tgruben
064ed9af1a
Merge branch 'master' into sup-146 2022-02-11 11:22:12 -06:00
Todd Gruben
8d5cdbdd77 roaring-migrate bug;performance improvements 2022-02-11 11:19:44 -06:00
Garrison Davis
33c7e16c24
Merge pull request #1917 from molecula/gd-examine-aws-perms
Investigating AWS credential issues
2022-02-11 09:32:57 -07:00
garrison.davis@molecula.com
054f7c6cce Make wget less noisy 2022-02-11 08:57:23 -07:00
garrison.davis@molecula.com
27024de323 Use profile explicitly 2022-02-11 08:55:57 -07:00
pokeeffe-molecula
90d897ad7d address merge conflict 2022-02-10 14:00:06 -06:00
pokeeffe-molecula
966a86e4de Merge branch 'master' into cicd-will-it-never-end 2022-02-10 13:59:40 -06:00
pokeeffe-molecula
bb1f403974 fixes to able defn 2022-02-10 13:56:59 -06:00
Garrison Davis
a21dd96b2d
Merge pull request #1912 from molecula/gd-instance-scale-in-protection
Stop termination in the gauntlet stage
2022-02-09 17:01:06 -07:00
Garrison Davis
26dc93d761
Merge branch 'master' into gd-instance-scale-in-protection 2022-02-09 16:41:59 -07:00
garrison.davis@molecula.com
62e6544089 Stop termination in the gauntlet stage
We have pipelines that get to the gauntlet stage then get failed because
the ASG scales-in before the gauntlet stage finishes. (4/6 of the last
gauntlet failures were from this failure.)

There are a few ways to fix this, but my proposal is to turn on scale-in
protection to stop scaling in the instance running the gauntlet job
(scale in other instances instead), then turn off the scale-in
protection after the gauntlet test is run.
2022-02-09 16:22:10 -07:00
Samir Patel
1dc0d2c88b
Merge pull request #1910 from molecula/pql-variables
[FB-1063] Dynamically expand queries based on $variable values
2022-02-09 16:58:33 -05:00
Samir Patel
96de9834bc
Merge branch 'master' into pql-variables 2022-02-09 14:40:18 -05:00
Samir Patel
39c9a062aa address feedback 2022-02-09 13:16:19 -06:00
Samir Patel
be68241d8e add test 2022-02-09 12:33:12 -06:00
Samir Patel
bfcbf9d784 change interfaceOrVariable type 2022-02-09 11:29:11 -06:00
pokeeffe-molecula
3a0777c063 added 'able' perf testing environment 2022-02-08 16:30:35 -06:00
Samir Patel
edc16a61ea remove comment 2022-02-08 16:08:04 -06:00
Samir Patel
4fee777c23 Merge branch 'pql-variables' of github.com:molecula/featurebase into pql-variables 2022-02-08 16:02:56 -06:00
Samir Patel
9e8b968c19 Refactor ExpandVars to reduce complexity 2022-02-08 15:58:12 -06:00
Samir Patel
cd0bdd4c30 refactor 2022-02-08 15:43:14 -06:00
Samir Patel
fbe23915cf support ConstRow expansion and cleanup 2022-02-08 13:39:22 -06:00
Matthew Jaffee
456e8d6417
Merge pull request #1907 from molecula/fb-1108-3-cleanup
Fb 1108 3 cleanup
2022-02-08 09:50:01 -06:00
Matthew Jaffee
04b13d9eb6 have test use the cluster.Start helper to avoid port conflicts
cluster.Start creates ephemeral ports for all the etcd stuff, whereas
node.Start uses the default config. I don't know why this test was
using the node.Start, but it passes without it.
2022-02-08 09:30:07 -06:00
Samir Patel
9a52dd1a2c handle rows for the most part 2022-02-07 20:00:05 -06:00
Ben Johnson
4fb795d6cb Parse variables for _field 2022-02-07 15:40:24 -07:00
Samir Patel
f5d0b227fa messing with parser, Rows call
messing around trying to get Rows call to recognize
$ syntax. got Rows to not barf, but it is interpreting $ syntax
as string values for the _field parameter as opposed to a Variable
2022-02-07 16:21:35 -06:00
Samir Patel
a755006d95 match on variable name, not field name 2022-02-07 15:43:32 -06:00
Matthew Jaffee
6cc5d198ee remove unused stuff and fix a bunch of random staticcheck issues
sorry... once I saw, I couldn't unsee
2022-02-07 15:10:10 -06:00
Matthew Jaffee
c2ed9ecdba remove InternalQueryClient 2022-02-07 15:10:10 -06:00
reese
6408debacf
Merge pull request #1905 from molecula/fb1172
fb1172: enable refresh tokens
2022-02-07 14:03:33 -06:00
reesporte
88d2914b15 fb1172: enable refresh tokens
- rip out gobby stuff
- add tokenCache, groupsCache
- refresh the token if needed
- set cookies after authenticate
- remove signature validation, the IDP does that for us
- added way more unit tests
- update older tests to use new API
- add fake idp to authcluster tests
2022-02-07 13:42:11 -06:00
Samir Patel
b3faaa9dc0 handle expanding of Row call
working for equality, but not for inequalityh ATM
2022-02-07 12:55:10 -06:00
reese
e8c123ca23
Merge pull request #1908 from molecula/log-index
log index with query for grpc
2022-02-04 16:53:39 -06:00
reesporte
8097e7dffd update test 2022-02-04 16:26:56 -06:00
reesporte
ede85735df use nfpm 2.11.3 so CI doesn't break 2022-02-04 16:12:20 -06:00
reesporte
1f8efd663c log index with query for grpc 2022-02-04 16:04:19 -06:00
Matthew Jaffee
36b721fd8d
Merge pull request #1902 from molecula/sup-139
[SUP-139] Fix GroupBy with multiple offset int groups
2022-02-04 11:34:36 -06:00
Ben Johnson
f824117df9 Fix GroupBy with multiple offset int groups 2022-02-04 09:36:59 -07:00
Matthew Jaffee
ed736b3cb3
Merge pull request #1904 from molecula/fb-1108-2-move-http-to-core
remove http subpackage and bring implementations into core
2022-02-04 08:56:10 -06:00
Matthew Jaffee
254bacc40c remove http subpackage and bring implementations into core
remove interfaces as necessary
2022-02-03 21:04:04 -06:00
Matthew Jaffee
0f0e418763
Merge pull request #1903 from molecula/kill-image-in-clustertests
get rid of 'image' in clustertests which was causing issues
2022-02-03 20:51:17 -06:00
Matthew Jaffee
2cc65ccae4 get rid of 'image' in clustertests which was causing issues 2022-02-03 17:00:49 -06:00
Matthew Jaffee
fac5bdbfbf
Merge pull request #1901 from molecula/fb-1114-2-rip-inspect
remove inspect command
2022-02-03 12:55:49 -06:00
Matthew Jaffee
d1f3b58861 remove inspect command 2022-02-03 11:25:31 -06:00
Matthew Jaffee
063bdaf41e
Merge pull request #1897 from molecula/fb-1114-rip-roaring
rip out roaring backend support
2022-02-03 11:16:23 -06:00
Matthew Jaffee
fea624f1ba fix typo w/ authclustertests 2022-02-02 21:05:33 -06:00
Matthew Jaffee
bff6b17a8e remove check command (was for roaring backend files) 2022-02-02 20:56:18 -06:00
Matthew Jaffee
1f371fa953 turn off verbose on linter, add smoke build
if your code doesn't build, the linter errors can be very misleading
2022-02-02 20:56:18 -06:00
Matthew Jaffee
70ea784d41 don't mind me, just submitting stuff that doesn't even compile and
then getting confused by linter errors
2022-02-02 20:56:18 -06:00
Matthew Jaffee
69c00a92ad remove a bunch of roaring backend stuff
snapshotQueue, op tracking, roaring-only tests
2022-02-02 20:56:18 -06:00
Matthew Jaffee
fa4855c887 remove unnecessary filter 2022-02-02 20:56:18 -06:00
Matthew Jaffee
e471b462b6 remove all occurences of Bitmap.Source 2022-02-02 20:56:18 -06:00
Matthew Jaffee
f8b180a4a5
Merge pull request #1900 from molecula/fix-clustertests
get container ID via "docker-compose" call in clustertests
2022-02-02 16:27:23 -06:00
Matthew Jaffee
979023392d authclustertests wasn't working because...
weirdness with the docker-compose file being in a different directory,
I think.
2022-02-02 15:08:04 -06:00
Matthew Jaffee
61783e5827 add option to set ResponseHeaderTimeout per client
this is necessary as in some cases we want a low timeout (when we
expect a quick response, e.g. with backup), but in others we may want
a very long timeout (long running query).

Now we have more granular control over timeouts so we can get things
to fail more predictably in tests.
2022-02-02 14:04:40 -06:00
Matthew Jaffee
06235c3d70 get container ID via "docker-compose" call in clustertests
this should be a lot more reliable than trying to construct it based
on the project name as the exact construction can differ between
docker-compose versions.

There was also an issue with the backups succeeding when they should
fail in the test. There's an arcane maze of HTTP timeouts to navigate
here, but basically there are situations where the client will just
wait forever rather than erroring if the server is paused at the
right(wrong) time. I'm not convinced we've solved every possible case
of this, so we still may see the backup succeed even when it's
supposed to fail. The ultimate hammer is to add Client.Timeout, but
that's a very blunt instrument and I'm afraid it could cause a timeout
when really we just have a lot of data to download or something.

There may be a better way to say "only time out if you literally
haven't heard a peep from the server in this long", but I haven't been
able to figure it out yet.

I also fixed how the authclustertests are run as they weren't using
the PROJECT parameter correctly. Now they can run concurrently with
clustertests, and with other copies of authclustertests without having
conflicts.
2022-02-02 12:03:46 -06:00
pokeeffe-molecula
e88c30c6cb
Merge pull request #1899 from molecula/cicd-will-it-never-end
remove dependence on gitlab artifact api; add s3 dump
2022-02-01 16:04:54 -06:00
pokeeffe-molecula
ca2def7389 dump to s3 2022-02-01 14:51:06 -06:00
pokeeffe-molecula
1e4b3321ff remove reliance on gitlab token 2022-02-01 14:40:38 -06:00
pokeeffe-molecula
6db05d6150 don't use gitlab api to get binaries 2022-02-01 14:22:24 -06:00
Ben Johnson
3989b363ce Add variable support to PQL 2022-02-01 08:30:48 -07:00
tgruben
8816583cd3
Merge pull request #1898 from molecula/sup-138
[SUP-138] add timestamp formatting to type FieldRow used in GroupBy
2022-01-31 14:52:54 -06:00
Todd Gruben
d7c082b515 add timestamp formating to type FieldRow used in GroupBy 2022-01-31 12:32:05 -06:00
souhailanoor
3ece8139fc
Merge pull request #1896 from molecula/auth-bug
FB1151-Enable auth for endpoint
2022-01-28 15:28:54 -06:00
Souhaila Noor
bae9d16c4f updated the tests 2022-01-28 14:28:59 -06:00
Souhaila Noor
20871a8780 remove asserting for log path 2022-01-28 13:07:22 -06:00
Souhaila Noor
1a4acfe97d fix bug with query bug 2022-01-28 13:01:08 -06:00
souhailanoor
baf5e47d8f
Merge branch 'master' into auth-bug 2022-01-28 12:12:19 -06:00
Souhaila Noor
f58ebbe505 enable auth for endpoint 2022-01-28 12:10:22 -06:00
pokeeffe-molecula
083670d20e
Merge pull request #1895 from molecula/cicd-will-it-never-end
added retries to go tests
2022-01-27 17:14:59 -06:00
pokeeffe-molecula
586e4d7f5a Merge branch 'master' into cicd-will-it-never-end 2022-01-27 15:50:21 -06:00
pokeeffe-molecula
d7401babd4 add retries....so these fracking flaky ass tests don't screw up the pipeline constantly 2022-01-27 15:49:54 -06:00
pokeeffe-molecula
1774062f24
Merge pull request #1894 from molecula/cicd-will-it-never-end
allow clustertests to fail
2022-01-27 15:24:44 -06:00
pokeeffe-molecula
7ff9e82b1b
Merge branch 'master' into cicd-will-it-never-end 2022-01-27 14:52:51 -06:00
pokeeffe-molecula
fedcdab1c2 allow clustertests to fail 2022-01-27 14:49:46 -06:00
pokeeffe-molecula
a8fd5f99f2
Merge pull request #1890 from molecula/fb1151-auth-tooling
FB-1151 auth tooling
2022-01-27 13:04:13 -06:00
pokeeffe-molecula
95605a4e59
Merge pull request #1891 from molecula/cicd-will-it-never-end
build roaring-migrate
2022-01-27 12:16:58 -06:00
souhailanoor
1d26739c90
Merge branch 'master' into fb1151-auth-tooling 2022-01-27 12:07:22 -06:00
pokeeffe-molecula
47f87f24c3
Merge branch 'master' into cicd-will-it-never-end 2022-01-27 11:42:40 -06:00
pokeeffe-molecula
05864f38df
Merge pull request #1893 from molecula/docker-is-messed-up
fix broken dockerfile
2022-01-27 11:42:14 -06:00
pokeeffe-molecula
d16ada75af use -o instead of a subsequent mv command 2022-01-27 11:36:16 -06:00
reesporte
1db6009d70 fix broken dockerfile
i think its gonna work this time!!!
2022-01-27 10:55:20 -06:00
pokeeffe-molecula
dff061ca22 now do it for the other one 2022-01-27 10:18:21 -06:00
pokeeffe-molecula
5d7c2437e9 trying again 2022-01-27 10:00:22 -06:00
pokeeffe-molecula
0f5ce612e0 building roaring-migrate for linux_amd64 2022-01-27 09:39:34 -06:00
pokeeffe-molecula
b67b8aff6c Merge branch 'master' into cicd-will-it-never-end 2022-01-27 09:38:14 -06:00
Souhaila Noor
0e1cf5bbbd Enable authentication/authorization for featurebase tools
- Add auth-token for featurebase import, backup and restore
- Add auth-token to http request
- Create a cluster tests with auth enabled
- Add test for import with auth enabled
2022-01-26 17:30:26 -06:00
Matthew Jaffee
d7c3fa2a93
Merge pull request #1889 from molecula/1174-projectify-clustertests
add project support to clustertests to allow for concurrent runs
2022-01-25 08:15:26 -06:00
Matthew Jaffee
71da3fdcb2 add docker-compose project to clustertests in CI to allow concurreny 2022-01-25 07:54:48 -06:00
Matthew Jaffee
7fbcba5c4b add GCP back in 2022-01-25 07:54:48 -06:00
Matthew Jaffee
3477534930 add project support to clustertests to allow for concurrent runs
also remove gcp tag... shouldn't be needed any more as I think the AWS
runners are properly configured.
2022-01-25 07:54:48 -06:00
pokeeffe-molecula
e0e86ec1d3 put docker containers in the right place 2022-01-24 18:34:14 -06:00
pokeeffe-molecula
8e775b88b9
Merge pull request #1875 from molecula/cicd-will-it-never-end
Added docker build & rpm, deb packaging for linux arm64
2022-01-24 17:15:13 -06:00
reese
de11a1d903
Merge pull request #1888 from molecula/fb1146
fb1146 - fixes panic on POST /transaction on non-primary node
2022-01-24 17:11:49 -06:00
reesporte
365789b791 remove unnecessary port bindings 2022-01-24 16:29:12 -06:00
pokeeffe-molecula
d389aae9c3
Merge branch 'master' into cicd-will-it-never-end 2022-01-24 16:12:54 -06:00
reesporte
ec543ac094 Merge branch 'master' into fb1146 2022-01-24 15:25:00 -06:00
reesporte
276088c386 fix panic on POST /transaction on non-primary node
- if we're a non-primary node, redirect to the primary
- if non-primary nodes can create transactions now, then the client should not receive an ErrNotPrimaryNode
- streamline metrics logic
2022-01-24 15:24:21 -06:00
pokeeffe-molecula
1721dd0dcf remove comments 2022-01-24 15:11:02 -06:00
Matthew Jaffee
10eac6fe9a
Merge pull request #1886 from molecula/fb-1116-rip-generation
rip out generation stuff
2022-01-24 11:52:12 -06:00
Matthew Jaffee
a2e109a07c disable roaring backend in test 2022-01-24 09:49:01 -06:00
Matthew Jaffee
2d44c23ac0 remove problematic roaring-only test 2022-01-24 09:49:01 -06:00
Matthew Jaffee
82c75851df rip out generation stuff
it was somewhat difficult to avoid ripping this out without also
touching some of the stuff that supports roaring backend. That's going
soon too, so no worries :)
2022-01-24 09:49:01 -06:00
Travis Turner
1d7a42c7e7
Merge pull request #1826 from molecula/tlt/rbf-comments
Clean up some of the godoc entries in rbf
2022-01-24 09:37:30 -06:00
Travis
07cd6ec228
Clean up some of the godoc entries in rbf 2022-01-22 07:52:36 -06:00
pokeeffe-molecula
bc89ca3553 now with real private_subnets! 2022-01-21 20:31:16 -06:00
pokeeffe-molecula
5241bd4ce4
Merge branch 'master' into cicd-will-it-never-end 2022-01-21 18:07:19 -06:00
reese
6d2f95e3fb
Merge pull request #1884 from molecula/fb1164
add test coverage
2022-01-21 14:29:46 -06:00
reesporte
836df379ac add test coverage
for the following auth related packages:
* authn
* http
* server

fix minor bugs, do some cleaning up, etc in `authn/authenticate.go` and `http/handler.go`
2022-01-21 13:57:47 -06:00
Ben Johnson
c7208cf5e3
Merge pull request #1882 from molecula/go-mod-v3
Upgrade go.mod to featurebase/v3
2022-01-21 12:53:09 -07:00
Ben Johnson
9ebf0e2119 Upgrade go.mod to featurebase/v3 2022-01-21 10:57:05 -07:00
seebs
4e578b8a65
Merge pull request #1879 from molecula/slowCI
bump test timeouts ridiculously
2022-01-21 11:52:54 -06:00
Seebs
03a18e9beb for leasedkv tests, don't use default etcd config
The default etcd config means that if two of this test run around the
same time, we end up with one of them failing because it can't bind.
Elsewhere, we resolve this by binding to ephemeral ports and fixing
up the config to use them, so we duplicate that here.

This includes duplicating the existing listenerWithURL from test/,
because that package has to import us, so we can't import it, and
I don't really want to make a separate package for one trivial
function.
2022-01-21 11:12:10 -06:00
Seebs
096c44884a fix typo in doc comment 2022-01-21 11:12:10 -06:00
Seebs
375aaf8fbc don't hardcode local port for backup and restore pprof service
If we hardcode a port, we can't run on a crowded machine, like in
CI. If we use :0, we can print the value actually picked.
2022-01-21 11:12:10 -06:00
Seebs
d50065a16f bump timeouts on single-writer RBF Tx test
There's no correct timeout value here, really, but the intent
of this is that we first want to be sure that a second tx doesn't
successfully start before the first exits, and then that the second
*does* successfully start *after* the first exits.

Unfortunately, there's no guarantees on timely processing, and in
reality, CI can break us by waiting more than 10ms before we get
enough CPU time to do something. More generally, there's no way to
make a test like this work correctly -- no matter how long you wait
for the second Tx to start before closing the first one, it's always
possible that it *would* have started just a millisecond later even
without you closing the first one. And similarly, no matter how long
you give it to start when it's *supposed* to, it could always take
longer.

We could in principle just set this to wait for the second Tx to start
and rely on the test timeout killing us if it doesn't, but then we
don't get a useful message.

Let's optimistically hope that 10 seconds is long enough for a trivial
rollback to happen, since that doesn't need to imply writes. And I
think 50ms is a better bet for the first test, although that does
make this test close to 5x slower on non-CI hardware.
2022-01-21 11:12:10 -06:00
Seebs
b40c86c278 retry etcd leader on "etcdserver: leader changed"
This should always be etcdserver.ErrLeaderChanged, but actually
apparently it's not always:

	non-retryable error: etcdserver: leader changed

The "non-retryable" comes from our code. The "leader changed"
message appears to come from etcdserver, but there appear to be
circumstances where it has a suffix, or it could get wrapped,
so we check for the string being contained in an error. This is
not pretty.
2022-01-21 11:12:10 -06:00
Seebs
b5fb9aad84 bump test timeouts ridiculously
gitlab CI runs as much as 5x slower sometimes during business hours,
resulting in tests failing due to 10-11 minute timeouts that would
succeed in under 2-3 minutes outside of business hours. to allow us
to do anything at all, let's just set that to half an hour, and 90
minutes for `go test -race`.

Concern: It's possible there's a timeout that's a gitlab CI configuration
thing involved too, because we see some go test timeout panics, but we
also see some weird messages about SIGQUIT at 11 minutes, which isn't
the go test timeout, so we may need to address that too.

Note that we're changing the Makefile, and also the config for the
gitlab CI passes, which don't use the Makefile. The Makefile changes
are just to be careful and avoid retriggering this later. We may
want to revert these if we get the other issues fixed.
2022-01-21 11:12:10 -06:00
Garrison Davis
71b03d8b85
Merge pull request #1883 from molecula/remove-go-caching
Remove go caching
2022-01-21 10:02:48 -07:00
garrison.davis@molecula.com
a93c3f2f71 Remove go caching
This will likely return when it's done in S3.
2022-01-21 09:55:23 -07:00
hphamMolecula
a179b15300
Merge pull request #1873 from molecula/ui-fixes
UI bug fixes
2022-01-21 09:55:04 -06:00
hphamMolecula
239832668b
Merge branch 'master' into ui-fixes 2022-01-20 17:09:37 -06:00
reese
d47ffdf5d7
Merge pull request #1880 from molecula/grpc-logging
grpc logging
2022-01-20 16:59:24 -06:00
hphamMolecula
0891f27a6a
Merge branch 'master' into ui-fixes 2022-01-20 16:38:34 -06:00
reese
647d62c8e7
Merge branch 'master' into grpc-logging 2022-01-20 15:51:21 -06:00
reese
efb5be8a67
Merge pull request #1878 from molecula/redirect-url
add a redirect-base-url config option
2022-01-20 15:51:00 -06:00
reesporte
81fcd9c228 fix merge conflicts 2022-01-20 14:14:25 -06:00
reesporte
9371212697 Merge branch 'master' into grpc-logging 2022-01-20 14:06:05 -06:00
reesporte
399a11223f use aws to run these jobs 2022-01-20 13:58:18 -06:00
reese
2e0aaa27a9
Merge branch 'master' into redirect-url 2022-01-20 13:08:16 -06:00
hphamMolecula
1d618a36ce
Merge branch 'master' into ui-fixes 2022-01-20 12:21:15 -06:00
Samir Patel
164c69bdf2
Merge pull request #1874 from molecula/keygen
update keygen subcommand
2022-01-20 13:19:09 -05:00
reesporte
87bbca938c add a redirect-base-url config option
this allows the user to configure a url for their IDP to redirect to, rather
than relying on the bind address of the featurebase server itself
2022-01-20 12:09:18 -06:00
hphamMolecula
ac54607a2c
Merge branch 'master' into ui-fixes 2022-01-20 09:42:01 -06:00
Samir Patel
dcdc90b961
Merge branch 'master' into keygen 2022-01-20 01:12:45 -05:00
reesporte
592fcbb05b one logger to rule them all
unify logging method, actually log query for streaming and unary requests
2022-01-19 21:20:08 -06:00
reese
06ed22ef93
Merge pull request #1877 from molecula/fb1167
fix bug with nil elements in protobuf indexes
2022-01-19 21:13:03 -06:00
reese
35343db29a
Merge branch 'master' into fb1167 2022-01-19 19:08:11 -06:00
seebs
ffbf55ee40
Merge pull request #1860 from molecula/rbfPages
RBF page/cursor management improvements
2022-01-19 18:27:52 -06:00
Seebs
fb11895985 oops handle nil 2022-01-19 17:09:57 -06:00
Seebs
749dcd6970 retry on etcd timeout errors 2022-01-19 16:57:47 -06:00
Samir Patel
16eff203ec
Merge branch 'master' into keygen 2022-01-19 16:38:31 -05:00
Seebs
2dce518a24 retry other etcd ErrTimeout variants
etcd can return more detailed ErrTimeout variants in rare cases, and we
want to retry on those too.
2022-01-19 15:19:45 -06:00
Seebs
37507db4ac use array containers instead of individual bitwise adds
This affects TestTx_Remove, TestTx_DeallocateToFreeList, and
TestTx_RecreateBitmap, all of which were adding hundreds of thousands
of individual bits, or more, and all of which work just as well and
produce the same behavior using largeish containers.

This reduces race-detector-test runtime from about 20 minutes to
a couple.
2022-01-19 15:19:45 -06:00
Seebs
719a30e128 shorten MultiTx test
The MultiTx test runs for a fairly long time but doesn't add much
value running that much longer, and there's no reason it should take
more than half the time we spend on this entire directory.
2022-01-19 15:19:45 -06:00
Seebs
112abcb549 use stable cursor for freelist operations
The Cursor datatype is quite large, and allocating them constantly for
ops is extremely expensive. To avoid this, we create a single stable cursor
that lives in the DB, and can be used for freelist modifications. Since the
freelist is only ever modified once at a time, this should be safe. We also
don't fully zero it between operations, we just reset the relevant parts.
2022-01-19 15:19:45 -06:00
Seebs
adcd5adb02 improve the sync.Pool used for pages, avoid excess page allocations for WAL
Several changes. One is, we don't provide a `New` for pagePool, which
allows allocPage to check whether a page was returned, and thus, zero
pages which were found in the pool, or make new pages, but never zero
pages it just created with make. We then also make many more things
which were making pages use the pool.

Reuse the same page allocation for multiple header pages dumped into
the WAL; the bitmap header pages aren't stashed in our page map,
they're only written to the disk, so we don't need to make a new page
each time, we can just make one new page for the whole batch.

Internally in the pool, we pool pointers to [PageSize]byte, rather
than slices. sync.Pool needs pointer-like things. To store a pointer
to a slice, you have to heap-allocate the slice, also. So, instead
of heap-allocating copies of these slices, we just use pointers to
the raw data.
2022-01-19 15:19:45 -06:00
hphamMolecula
b7e85db4b3
Merge branch 'master' into ui-fixes 2022-01-19 15:16:05 -06:00
reesporte
a162322fc9 fix bug with nil elements in protobuf indexes
we were allocating space we weren't using smh my head
2022-01-19 14:53:35 -06:00
reese
49972939ec
Merge pull request #1876 from molecula/fb1166
fix bug where drop table wasn't being authorized
2022-01-19 14:26:04 -06:00
reesporte
61ef1aee4e fix older tests 2022-01-19 12:55:07 -06:00
reesporte
e7552a76a7 fix bug where drop table wasn't being authorized
also fixes bug in GetAuthorizedIndexList where perms weren't being properly compared
2022-01-19 12:08:05 -06:00
pokeeffe-molecula
27f1fcbf45
Merge branch 'master' into cicd-will-it-never-end 2022-01-19 11:59:34 -06:00
pokeeffe-molecula
c2c140aad4 print out the url of the binary we are trying to get 2022-01-19 11:26:40 -06:00
Samir Patel
e1d7389893
Update ctl/keygen.go
Co-authored-by: reese <45641995+reesporte@users.noreply.github.com>
2022-01-19 11:23:02 -05:00
pokeeffe-molecula
bc589ee4eb when it fails, it should fail 2022-01-19 10:13:11 -06:00
Samir Patel
950e62aae9 update keygen subcommand
this updates the subcommand to output a single secret key
instead of two reflecting changes made to AuthN/authZ
2022-01-19 10:11:19 -06:00
pokeeffe-molecula
b144c0e61c added ARG decl. 2022-01-19 10:10:30 -06:00
hphamMolecula
580a6109fb
Merge branch 'master' into ui-fixes 2022-01-19 10:04:35 -06:00
pokeeffe-molecula
ec76cb5b34 added .deb & .rpm package for arm64 2022-01-18 18:14:51 -06:00
pokeeffe-molecula
4ab3c32211 build docker for arm64 2022-01-18 18:08:59 -06:00
Hoang Pham
c969a8370e UI - added fix for Query Builder page showing up as blank when there are no tables associated with current user 2022-01-18 17:57:40 -06:00
reese
8834d211af
Merge pull request #1872 from molecula/build-lattice-improvements
actually be able to generate-statik
2022-01-18 15:43:30 -06:00
reesporte
fdf7b4107a actually be able to generate-statik
these were the changes i had to make to be able to build lattice on my machine
2022-01-18 12:14:54 -06:00
Samir Patel
695321e6c0 print attr 2022-01-17 20:47:27 -06:00
Matthew Jaffee
50f798cb18
Merge pull request #1870 from molecula/gitlab-ci-parity
add race and shardwidth22 tests to gitlab
2022-01-17 20:43:57 -06:00
Samir Patel
70b1ef906f switch on req type 2022-01-17 20:41:57 -06:00
Matthew Jaffee
8b5fdf40fc
Merge branch 'master' into gitlab-ci-parity 2022-01-17 16:35:50 -06:00
Matthew Jaffee
22a60a19f8
Merge pull request #1869 from molecula/qol-tweak
clean up files generated by tests
2022-01-17 16:35:24 -06:00
Matthew Jaffee
a16fee5f88 set shardWidth properly in client
the shardwidth22 tests were broken client side, but we didn't realize
this because we weren't running the client side tests since moving the
client code into the main FB repo until recently (woops), and more
recently, we'd stopped running the shardwidth22 tests in the move to
Gitlab, so when we re-enabled them we finally noticed that they were
broken in the client.

All this change does is takes the shardWidth value from the core
featurebase package instead of using a hardcoded value in the client package.
2022-01-17 10:57:01 -06:00
Matthew Jaffee
da03e3fad2 add race and shardwidth22 to Gitlab CI, cleanup
our coverage reporting was a bit wonky and had files coming from both
test and test-future... made everything come from future
2022-01-17 10:12:40 -06:00
Matthew Jaffee
e297a6775d have simulacradata tests clean up generated files 2022-01-17 09:39:28 -06:00
reese
80f9ddaa02
Merge pull request #1868 from molecula/security-logging
FB1109: authn/z audit logging
2022-01-15 12:43:32 -06:00
reesporte
04a51a7819 remove shadowed ok
thanks golangci-lint
2022-01-15 12:25:09 -06:00
reesporte
50f9b0d1b6 Merge branch 'master' into security-logging 2022-01-15 12:21:38 -06:00
reesporte
7644922406 adds logging to all network requests
addresses ticket FB-1109:
when auth is turned on, we log:
- source ip (if available)
- user-agent
- user id
- user name
- query string
- request endpoint

also adds some minor tweaks and comments  to chkAuthZ flow
2022-01-15 12:21:27 -06:00
Matthew Jaffee
231a395138
Merge pull request #1867 from molecula/external-lookup-gitlab
get external-lookup tests running in Gitlab CI
2022-01-15 08:13:10 -06:00
Matthew Jaffee
d5bd031451 better error reporting if delete fails 2022-01-14 21:09:16 -06:00
Matthew Jaffee
a08560d01e get external-lookup tests running in Gitlab CI
I was going to write a docker-compose thing for this to run postgres
alongside the Go tests, but then saw that Gilab has this handy-dandy
notion of a service, so used that.
2022-01-14 21:09:16 -06:00
reese
f9c7ff3629
Merge pull request #1866 from molecula/fb1130
[fb-1130]: filter http response and lockdown endpoints
2022-01-14 17:45:51 -06:00
reesporte
3fdf4e2d8b Merge branch 'master' into fb1130 2022-01-14 16:06:45 -06:00
reesporte
baf02748be filter http response and lockdown endpoints
- fixes required permissions on some http endpoints
- filters http endpoints:
    - /ui/usage
    - /schema
    - /schema/details
- filter GRPC show tables, fields
- allow admins to do anything
2022-01-14 16:05:54 -06:00
Matthew Jaffee
34c64fbaba
Merge pull request #1865 from molecula/wrapping-etcd-retry
add wrapping to differentiate etcd errors
2022-01-14 15:58:56 -06:00
Matthew Jaffee
555d185929 add wrapping to differentiate etcd errors
we had a CI job fail in an interesting way, but can't tell if the
etcd retrying stuff is working, so adding in this wrapping so we can
better differentiate the errors if we see it again.

Job is here: https://gitlab.com/molecula/featurebase/-/jobs/1977060827

Failure is:

```
=== RUN   TestClusterStuff
    cluster_test.go:36: creating index: against http://pilosa2:10101/index/testidx 404 Not Found: 'creating index: sending CreateIndex message: executing request: against http://pilosa3:10101/internal/cluster/message 500 Internal Server Error: 'processing message: getting index: testidx: etcdserver: request timed out
        ''
--- FAIL: TestClusterStuff (8.85s)
```
2022-01-14 14:01:37 -06:00
reesporte
06c34c9f3e Merge branch 'master' into ui-fixes 2022-01-14 13:56:47 -06:00
reese
605da1e074
Merge pull request #1861 from molecula/bearer-conversion-squashed
[fb-998] [fb-1131] [fb-1129] addresses multiple authn/z tickets
2022-01-14 13:52:24 -06:00
reesporte
68c6bffa2c clear localstorage on sign out 2022-01-14 13:02:01 -06:00
reesporte
89567b791b Merge branch 'master' into bearer-conversion-squashed 2022-01-14 12:34:22 -06:00
Matthew Jaffee
b2afe7ad3b
Merge pull request #1863 from molecula/moar-cicd-clustertests
add clustertests to gitlab CI
2022-01-14 12:32:40 -06:00
reesporte
9f37cf7b48 Merge branch 'master' into bearer-conversion-squashed 2022-01-14 12:32:06 -06:00
reesporte
cf2410fea6 addresses multiple authn/z tickets
* fb-998 - authn/z enabled in handlers (kitchen-sink ticket)
    - authorization is enabled through the use of a bearer token (using header "Authorization")
    - authorization may occur through the use of an "Authorization" header or "molecula-chip" cookie
    - ui is updated for changes to handler
* fb-1131 - protect grpc endpoints
    - GRPC endpoints now check authorization if auth is enabled
* fb-1129 - inter-node communication
    - the following endpoints use the secretKey for authentication:
        - /internal/cluster/message: POST
        - /internal/translate/data: GET, POST

* added test to api_test.go (TestAuth_MultiNode) testing various auth/permissions stuff on a multi-node cluster

not included:
    - fb-1130 - filter response of endpoints
    - fb-1109 - improved audit logging

@jaffee [are you not entertained](https://www.youtube.com/watch?v=mutgotxrcqg)

Co-authored-by: souhailanoor <90720110+souhailanoor@users.noreply.github.com>
Co-authored-by: tgruben <tgruben@gmail.com>
Co-authored-by: 54mir <48686912+54mir@users.noreply.github.com>
Co-authored-by: kcrodgers24 <49999391+kcrodgers24@users.noreply.github.com>
2022-01-14 12:31:32 -06:00
Matthew Jaffee
2f30bcda45 add clustertests to gitlab CI
had to install some dependencies and things on the runner which are
detailed in a comment.
2022-01-14 11:05:41 -06:00
pokeeffe-molecula
f6c458b093
Merge pull request #1862 from molecula/cicd-smoketest
Now with working integration testting
2022-01-13 15:27:17 -06:00
pokeeffe-molecula
0b9d108626
Merge branch 'master' into cicd-smoketest 2022-01-13 14:52:24 -06:00
pokeeffe-molecula
dcc295b25d fixed broken shell script 2022-01-13 14:24:44 -06:00
Matthew Jaffee
5048c8712f
Merge pull request #1859 from molecula/fieldView
[SUP-132] track field directly in view to prevent deadlocks
2022-01-13 13:50:33 -06:00
pokeeffe-molecula
ff16924a0a fixed path typo 2022-01-13 13:31:41 -06:00
Matthew Jaffee
dad244e0d3 skip sometimes-failing test of experimental code
this is killing us in CI for no good reason
2022-01-13 13:16:57 -06:00
Seebs
6fba8aba8b track field directly in view to prevent deadlocks
The central reason this exists:

**sync.RWMutex can block read locks even when no write lock is yet held.**

If a write lock is *requested*, this can block future read locks. In
particular, this means that recursive read locks are unsafe. But there's
additional problems.

The specific case that bit us involves not two, but *three* things
running at once.

Thing #1: executor doing AvailableShards. This RLocks the index, and
then each field, and then each view. To complete, it must be able to
obtain a read lock on each view in turn.

Thing #2: DeleteField. This Locks the index. Even if it is stuck
waiting for the lock (which it will be until AvailableShards completes),
it can prevent *additional* RLocks of the index.

Thing #3: CreateFragment. This Locks a view, then RLocks the index in
order to look up a field.

CreateFragment can't proceed until DeleteField completes. DeleteField
can't proceed until AvailableShards completes. And AvailableShards
can't proceed until CreateFragment completes.

Solution: Cache the *Field in the view, so we don't need a read lock
on the field or index to complete a CreateFragment.
2022-01-13 13:16:57 -06:00
pokeeffe-molecula
f4d28b840a stop gauntlet from running every build 2022-01-13 13:00:02 -06:00
pokeeffe-molecula
da3cabe642 Merge branch 'master' into cicd-smoketest 2022-01-13 12:57:42 -06:00
pokeeffe-molecula
04a2df3036 added basic integration tests 2022-01-13 12:57:26 -06:00
Matthew Jaffee
4a1e53421e
Merge pull request #1858 from molecula/retryEtcd
[SUP-130] handle ErrTimeout in etcd embed "retryClient"
2022-01-13 12:54:10 -06:00
Seebs
84adefe6a5 handle ErrTimeout in etcd embed "retryClient"
This tries to be more correct/careful about retries (checking against
the actual exported errors from etcdserver, not just the string
representations), and also supports retrying on timeouts, not just
on client changes. It can also retry more than once, mostly in case
we hit one of each of those.

For timeout errors, we mostly use the fact that it's a timeout to
give us a reasonable backoff, but then delay a fraction of a second
longer just to give it a moment to recover if the ErrTimeout is
masking something else that took longer.
2022-01-13 11:47:57 -06:00
Bruce Baranowski
c60bed21c3
Merge pull request #1840 from molecula/IO-47
added tags to sg terraform
2022-01-12 19:18:04 -05:00
bruce-b-molecula
ef5736c73e added tags to sg terraform 2022-01-12 18:59:28 -05:00
Ben Johnson
24c38cd6b9
Merge pull request #1848 from molecula/fb-828
[FB-828] Fix RBF WAL size check
2022-01-12 09:59:01 -07:00
Ben Johnson
a49a14652f Fix RBF WAL size check
This commit changes the max WAL size calculation to double the
number of bitmap pages in the WAL as they require an extra header
page. Previously, this was causing the WAL to be overrun and
references to those pages were outside the mmap range and caused a
panic.
2022-01-12 08:26:14 -07:00
pokeeffe-molecula
5f5caff30d
Merge pull request #1855 from molecula/cicd-smoketest
Really get gauntlet to run in master
2022-01-11 18:42:02 -06:00
pokeeffe-molecula
24a963ef52
Merge branch 'master' into cicd-smoketest 2022-01-11 18:27:22 -06:00
pokeeffe-molecula
d896953af4 stop gauntlet from running on push 2022-01-11 18:08:14 -06:00
pokeeffe-molecula
8919d9d5d3 change the way we call ssh 2022-01-11 15:51:18 -06:00
Matthew Jaffee
afc1cd62b7
Merge pull request #1853 from molecula/fb-1115-rip-rowcache
FB-1115 rip out rowcache
2022-01-11 14:10:05 -06:00
Matthew Jaffee
34393dee09 rip out rowcache
not strictly backward compatible... hopefully no one is actually using
the rowcache config option
2022-01-11 13:49:09 -06:00
pokeeffe-molecula
c647c0c079
Merge pull request #1851 from molecula/cicd-smoketest
Cicd smoketest
2022-01-11 12:56:07 -06:00
pokeeffe-molecula
7e8d217208 so much fail... 2022-01-11 12:21:38 -06:00
pokeeffe-molecula
5056a8ea4d Update .gitlab-ci.yml 2022-01-11 11:39:45 -06:00
pokeeffe-molecula
562d665014
Merge branch 'master' into cicd-smoketest 2022-01-11 11:37:23 -06:00
Matthew Jaffee
951368acea
Merge pull request #1852 from molecula/fb-1118-commented-prints
remove a bunch of commented print statements and unecessary prints
2022-01-11 11:08:48 -06:00
pokeeffe-molecula
130c2265ca
Merge branch 'master' into cicd-smoketest 2022-01-11 11:00:58 -06:00
Matthew Jaffee
df88b5a78c remove a bunch of commented print statements and unecessary prints 2022-01-11 10:42:44 -06:00
Matthew Jaffee
888e68f884
Merge pull request #1847 from molecula/1147-slow-int-import
FB-1147 FB-1149 add sorting for ints/mutex in batch importer
2022-01-11 10:41:45 -06:00
pokeeffe-molecula
994ba6f597 ignore in sonarcloud 2022-01-11 10:30:28 -06:00
Matthew Jaffee
48b4169cb5 refactor client batch tests to reduce duplication
also use a single cluster with each test creating a different index
rather than each test creating a whole new cluster.

runtime went from 38s to 30s in my informal tests
2022-01-11 10:17:43 -06:00
Matthew Jaffee
db87a3c4f7 fix vet shadow issue 2022-01-11 10:15:58 -06:00
Matthew Jaffee
7fbd371038 get some of the client tests to actually *run*
discovered that client tests weren't running due to integration build
tag. Fixed the file I needed to get through SonarCloud and documented
rest of what needs to be done in FB-1152 https://molecula.atlassian.net/browse/FB-1152
2022-01-11 10:15:58 -06:00
Matthew Jaffee
131f891f75 fix up error messages in client batch test 2022-01-11 10:15:58 -06:00
Matthew Jaffee
6335b9c801 disable retryablehttp logger because *wow* that's a lot of output 2022-01-11 10:15:58 -06:00
Matthew Jaffee
16161025f2 trying to get sonar coverage reporting working
looks like test-report.out and coverage.out aren't about the same
tests. I'm unclear on how sonar uses tests.reportPaths vs
coverage.reportPaths, but figured I'd try at least generating them
from the same run to see if that helped.
2022-01-11 10:15:58 -06:00
Matthew Jaffee
55a385ed2d add sorting for ints/mutex in batch importer
fixes pathological case where imports with randomly ordered IDs which
spanned multiple shards and included ints or mutex fields could be
incredibly slow due to making 1000s of requests.
2022-01-11 10:15:58 -06:00
reese
ce8b5fa323
Merge pull request #1849 from molecula/fb-1148
distinct on timestamps can reduce now
2022-01-11 09:52:52 -06:00
pokeeffe-molecula
4bcdb817a5 Merge branch 'master' into cicd-smoketest 2022-01-11 08:49:03 -06:00
pokeeffe-molecula
394a6e9854 switching gauntlet to scheduled 2022-01-11 08:47:02 -06:00
pokeeffe-molecula
4b192ee8bf added progress reporting 2022-01-10 18:02:45 -06:00
pokeeffe-molecula
5ec9d7cf96 Now with more gauntlet 2022-01-10 16:11:03 -06:00
reesporte
1f370744c5 add multi-shard test for distinct(timestamp) 2022-01-10 15:41:30 -06:00
reesporte
cf483aca77 distinct on timestamps can reduce now 2022-01-10 13:07:57 -06:00
pokeeffe-molecula
e4e667215f try to run full gauntlet 2022-01-10 12:19:06 -06:00
pokeeffe-molecula
d35273c3b5 Update .gitlab-ci.yml 2022-01-10 11:59:32 -06:00
pokeeffe-molecula
d3b64941a5 fix yaml (again) 2022-01-10 10:42:48 -06:00
pokeeffe-molecula
63bf6dee2e fix yaml 2022-01-10 10:38:11 -06:00
pokeeffe-molecula
d4e9852b09 try to get gauntlet to run e2e on GitLab 2022-01-10 10:28:51 -06:00
pokeeffe-molecula
320ae1a8b2 make test failures clearer 2022-01-10 08:24:11 -06:00
pokeeffe-molecula
286953c5fc getting gauntlet working 2022-01-09 11:53:14 -06:00
pokeeffe-molecula
b82e05b012
Merge pull request #1843 from molecula/cicd-smoketest
make sure gauntlet does not run unless scheduled
2022-01-08 17:09:49 -06:00
pokeeffe-molecula
6dee0d1ec2 changes 2022-01-08 16:42:23 -06:00
pokeeffe-molecula
a5c36d5c21 remove un-needed files 2022-01-08 16:00:46 -06:00
pokeeffe-molecula
4743624210 refactored scripts for imperative setup and execution 2022-01-08 15:35:57 -06:00
pokeeffe-molecula
bb434639ad cleaning up terraform to put in pre-prepared VPC 2022-01-07 17:25:48 -06:00
pokeeffe-molecula
b864d6b6f1 un-broke some stuff 2022-01-07 13:40:35 -06:00
pokeeffe-molecula
eb60fb301f Merge branch 'master' into cicd-smoketest 2022-01-07 11:58:10 -06:00
pokeeffe-molecula
c0161b6bbc
Merge pull request #1846 from molecula/cicd-mitigations
disable gauntlet
2022-01-07 11:18:10 -06:00
pokeeffe-molecula
219322b675 fix ordering of rules 2022-01-07 10:43:52 -06:00
pokeeffe-molecula
5779b1c036 disable gauntlet 2022-01-07 10:12:20 -06:00
reese
2494aaf959
Merge pull request #1845 from molecula/staticcheck-file-perm-fix
fix file perms to be _actually_ 600
2022-01-07 10:06:47 -06:00
reesporte
bebc54b4e2 fix file perms to be _actually_ 600
based on staticcheck results:
server/server.go:627:58: file mode '600' evaluates to 01130; did you mean '0600'? (SA9002)
server/server.go:632:65: file mode '600' evaluates to 01130; did you mean '0600'? (SA9002)
2022-01-07 09:30:11 -06:00
Fletcher Haynes
3b2ee2a15c .gitlab/.gitlab-ci.yml 2022-01-07 07:17:00 -08:00
Fletcher Haynes
369c91daf9 Fixed a few more things 2022-01-07 07:04:01 -08:00
Fletcher Haynes
d328ead713 Resolved conflicts 2022-01-07 06:59:08 -08:00
Fletcher Haynes
70833218b1 Added in auto-peering of smoketest VPC 2022-01-07 06:58:02 -08:00
pokeeffe-molecula
574be963ec follow up changes to get vpn working - still no dice 2022-01-06 20:13:52 -06:00
Fletcher Haynes
56cf9f43f5 Added in connecting the gauntlet VPC to a VPC that can be reached via the VPN 2022-01-06 17:07:14 -08:00
pokeeffe-molecula
e550925fba changes 2022-01-06 19:00:00 -06:00
Kasey C. Rodgers
801d1e3e73
Merge pull request #1844 from molecula/fix-tls-check
correct TLS enabled check
2022-01-06 10:55:17 -08:00
Fletcher Haynes
1e2aa7c807 Changed smoke test to allow failure 2022-01-06 10:36:20 -08:00
kcrodgers24
5dfca76fbb correct TLS enabled check 2022-01-06 09:29:03 -08:00
Samir Patel
2469d7e61c
Merge pull request #1830 from molecula/protect-endpoints
[FB-1023] Protect endpoints
2022-01-06 11:52:40 -05:00
Samir Patel
41bde6ccba don't write content to no content 2022-01-06 10:35:11 -06:00
Samir Patel
6e9efd0e09 Merge branch 'protect-endpoints' of github.com:molecula/featurebase into protect-endpoints 2022-01-05 17:30:18 -06:00
Samir Patel
3fe381ff22 address feeback 2022-01-05 17:29:59 -06:00
reese
7881b0987f
Merge branch 'master' into protect-endpoints 2022-01-05 17:24:41 -06:00
pokeeffe-molecula
183d30073d
Merge branch 'master' into cicd-smoketest 2022-01-05 16:20:27 -06:00
pokeeffe-molecula
c5e91420cc make sure gauntlet does not run unless scheduled 2022-01-05 16:19:47 -06:00
pokeeffe-molecula
4268804a46
Merge pull request #1842 from molecula/cicd-smoketest
Cicd smoketest
2022-01-05 15:55:42 -06:00
pokeeffe-molecula
1fccfabc8f changes based on feedback 2022-01-05 15:35:38 -06:00
pokeeffe-molecula
6959c424e3 getting smoke test report to show 2022-01-05 14:39:45 -06:00
pokeeffe-molecula
a2ee26b57c running all of gauntlet in schedule 2022-01-05 12:25:41 -06:00
reesporte
fd896de270 rename CookieValue to AuthContext
because we're not using cookies anymore
2022-01-05 12:10:33 -06:00
pokeeffe-molecula
03fc5d470d I give up...we're sleeping 2022-01-04 22:11:38 -06:00
pokeeffe-molecula
6c8e309e70 added connection timeout 2022-01-04 21:30:06 -06:00
pokeeffe-molecula
f5b669508b getting node deployed; first test 2022-01-04 20:55:23 -06:00
pokeeffe-molecula
2f68b2a6f6 set data nodes to 1; refine cluster test 2022-01-04 19:57:37 -06:00
pokeeffe-molecula
97fc84ef17 fixed filenames for output 2022-01-04 19:31:18 -06:00
pokeeffe-molecula
f51834be82 declare the cluster_prefix variable 2022-01-04 18:37:18 -06:00
pokeeffe-molecula
2e0812ed98 variable fix 2022-01-04 18:09:16 -06:00
pokeeffe-molecula
ca5633c594 add uniqueness to cluster prefix 2022-01-04 16:36:11 -06:00
reesporte
e335886741 adding Groups Struct back in
"It was pure hubris that brought us to this point."
2022-01-04 16:23:25 -06:00
reesporte
8d6490329b Merge branch 'master' into protect-endpoints 2022-01-04 16:18:18 -06:00
Samir Patel
23a1b4c536 revisions and docs 2022-01-04 16:02:25 -06:00
pokeeffe-molecula
cfacc72c53 smoking or non-smoking? 2022-01-04 15:00:39 -06:00
pokeeffe-molecula
094f70a91a
Merge pull request #1839 from molecula/pipeline-scheduling
Pipeline scheduling
2022-01-04 14:15:29 -06:00
pokeeffe-molecula
13b6f6f133 re-enabling actual test 2022-01-04 13:02:45 -06:00
pokeeffe-molecula
a2be201009 fixed yaml fubar 2022-01-04 12:37:05 -06:00
pokeeffe-molecula
c06d21a189 rules it is.. 2022-01-04 12:33:45 -06:00
pokeeffe-molecula
624975e123 getting scheduling to work 2022-01-04 11:29:00 -06:00
Samir Patel
8690160dd4
Merge pull request #1812 from molecula/54mir/authentication
[FB-1014] Authentication
2022-01-04 09:43:56 -05:00
Samir Patel
ab4e4ac216
Merge branch 'master' into 54mir/authentication 2022-01-04 09:28:58 -05:00
pokeeffe-molecula
c5a75fcd66
Merge pull request #1838 from molecula/get-pipeline-to-run
just run it all the time for now
2022-01-03 23:20:22 -06:00
pokeeffe-molecula
cc9c2761be
Merge branch 'master' into get-pipeline-to-run 2022-01-03 23:19:34 -06:00
pokeeffe-molecula
b4da2be804 just run it all the time for now 2022-01-03 23:19:07 -06:00
Samir Patel
414dff1d22 revisions 2022-01-03 22:56:21 -06:00
pokeeffe-molecula
3e31035e29
Merge pull request #1837 from molecula/get-pipeline-to-run
disabling single node deploy
2022-01-03 22:46:09 -06:00
pokeeffe-molecula
65a2deb842
Merge branch 'master' into get-pipeline-to-run 2022-01-03 22:45:13 -06:00
pokeeffe-molecula
44d635f407 disabling single node deploy 2022-01-03 22:43:25 -06:00
Samir Patel
d537398568
Merge branch 'master' into 54mir/authentication 2022-01-03 23:33:45 -05:00
pokeeffe-molecula
5f8b78ba9a
Merge pull request #1836 from molecula/get-pipeline-to-run
fix gitlab pipeline; disable circleci; remove artifactory
2022-01-03 22:22:06 -06:00
pokeeffe-molecula
56584905c2 fix gitlab pipeline; disable circleci; remove artifactory 2022-01-03 22:11:30 -06:00
pokeeffe-molecula
61c0ef9a1e
Merge pull request #1835 from molecula/fix-failed-deploy-linux-node
Fix failed deploy linux node
2022-01-03 21:50:21 -06:00
Fletcher Haynes
b9e8d3a103 Commented out a failing test as a meta-test 2022-01-03 19:17:11 -08:00
Fletcher Haynes
70a3af97a8 Fixed some variables in the CI file 2022-01-03 19:05:39 -08:00
Samir Patel
a7fada30dd revisions 1 2022-01-03 20:43:51 -06:00
Fletcher Haynes
c0708e5403 Changed the env vars a CI job was accessing 2022-01-03 16:48:42 -08:00
tgruben
16600a219c
Merge branch 'master' into 54mir/authentication 2022-01-03 17:55:58 -06:00
Fletcher Haynes
58a70863eb
Merge pull request #1823 from molecula/fb901
Fb901
2022-01-03 15:51:24 -08:00
Samir Patel
1b10f26258 fix permission stuff for write queries 2022-01-03 17:41:09 -06:00
Samir Patel
7834db2347 change write call detection 2022-01-03 16:24:14 -06:00
Fletcher Haynes
a40d974377
Merge branch 'master' into fb901 2022-01-03 14:20:08 -08:00
pokeeffe-molecula
51ad67e06a
Update qa/tf/gauntlet/samsung/README.md
Co-authored-by: reese <45641995+reesporte@users.noreply.github.com>
2022-01-03 16:09:26 -06:00
pokeeffe-molecula
804b7b3146
Update qa/tf/README.md
Co-authored-by: reese <45641995+reesporte@users.noreply.github.com>
2022-01-03 16:06:54 -06:00
Ben Johnson
379c5e0bd1
Merge pull request #1832 from molecula/rbf-no-panic
Avoid panics in RBF debug tooling
2022-01-03 13:43:10 -07:00
Fletcher Haynes
e89c04acaf
Merge branch 'master' into fb901 2022-01-03 12:25:26 -08:00
Fletcher Haynes
4016a1d03d Fixed commenting in the gitlab CI file. 2022-01-03 12:21:32 -08:00
garrison.davis@molecula.com
fa9ae13363 Adds gauntlet testing framework for Samsung
This adds the Terraform needed to create a gauntlet testing framework for a cluster that is a mirror of Samsung's. It is meant to be run once a day in CI via the GitLab scheduler.
2022-01-03 12:15:07 -08:00
Ben Johnson
af9795aa1a Avoid panics in RBF debug tooling 2022-01-03 13:13:02 -07:00
tgruben
d5dcdcd40a
Merge branch 'master' into 54mir/authentication 2022-01-03 12:45:15 -06:00
reese
080ea6ad2e
Merge pull request #1806 from molecula/percentile-timestamp-decimal
FB-1095 implement percentiles on timestamp/decimal
2022-01-03 12:26:05 -06:00
tgruben
fb5765676b
Merge branch 'master' into 54mir/authentication 2022-01-03 12:15:10 -06:00
Samir Patel
d18b739402 add test cases 2022-01-03 11:49:38 -06:00
reesporte
b13538e426 update doc comment 2022-01-03 11:16:14 -06:00
reesporte
72adb177ae Merge branch 'master' into percentile-timestamp-decimal 2022-01-03 11:12:23 -06:00
reesporte
6e3ce01ecb explicitly test that getScaledInt works with timestamps 2022-01-03 11:11:54 -06:00
reesporte
fa2391b948 explicitly test untested path of valcountize 2022-01-03 11:11:27 -06:00
reesporte
99f6a1c113 change min to val
bc it could be used for things besides mins
2022-01-03 10:45:23 -06:00
Fletcher Haynes
93b97b9831 Test push to see if pipeline is running on push to master 2021-12-30 17:00:59 -08:00
reesporte
9b77432952 fix bad formatting 2021-12-29 14:22:29 -06:00
Samir Patel
c0fe253ce2 Merge branch 'protect-endpoints' of github.com:molecula/featurebase into protect-endpoints 2021-12-29 14:41:49 -05:00
Samir Patel
cf86be16c1 add authN only middleware for /internal 2021-12-29 14:41:31 -05:00
reesporte
8e697c0d8c Merge branch 'protect-endpoints' of github.com:molecula/featurebase into protect-endpoints 2021-12-29 13:38:55 -06:00
reesporte
17679eb924 create a Permissions type
makes it nice to say p.Satisfies(otherPerm)
2021-12-29 13:38:11 -06:00
Samir Patel
7750900310 more logging 2021-12-29 13:18:42 -05:00
reesporte
be66103c45 requirements when auth is enabled
postgres binding is turned off
TLS must be turned on
2021-12-29 11:20:19 -06:00
reesporte
2847c22a4c linter things 2021-12-29 11:06:58 -06:00
reesporte
42f3557c55 fix merge conflicts 2021-12-29 09:05:53 -06:00
Samir Patel
d95d4dac9d pass group membership thru context 2021-12-28 17:36:52 -05:00
Travis Turner
56b9e2aba7
Merge pull request #1831 from molecula/tlt/ignore-down
Stop blocking API called when cluster is DOWN or DEGRADED
2021-12-28 14:14:29 -06:00
Travis
ffd91137e1
Stop blocking API called when cluster is DOWN or DEGRADED
This commit effectively removes the API-level validation that was
blocking certain API methods when the cluster was in a particular state
(namely DOWN and DEGRADED). The thinking is that we shouldn't be
blocking these requests at the API level, but rather should let them
pass through and allow the fact that a node is ACTUALLY down dictate the
behavior.

With this change, two tests were modified. They were previously
expecting the error message from the API validation on DOWN, but now
they check for a "shard unavailable" error, which is what gets returned
for a particular query when the cluster is in an unhealthy state.
2021-12-28 13:52:04 -06:00
Matthew Jaffee
6fd985c8eb
Merge pull request #1828 from molecula/errant-print
fix retry period and change client DialTimeout for commands (e.g. restore/backup)
2021-12-28 13:51:28 -06:00
Matthew Jaffee
1a8c10d5f3 fix backup fail test so it actually fails
A few things were going wrong here.

First, we take a "RetryPeriod" option on backup and restore which is
meant to be roughly the total amount of time we spend retrying any
given request before failing. However we were incorrectly passing that
as the RetryMaxWait which is the maximum amount of time to sleep
between any two attempts. We now do some fuzzy math to figure out
approximately how many attempts we should make given a minimum sleep
of 100ms and the fact that we double the sleep time every attempt.

Second, during the backup test, if a host was totally stopped when we
started the request, it would fail immediately and then retry, but if
the host was stopped during the request (after DNS had resolved), then
the request would wait for the DialTimeout which we default to 30s, so
turning off the cluster for 5 seconds and turning it back on resulted
in the backup completing rather than failing. Because of this, we
change the commandClient to have a default dial timeout of 1 second.

I was tempted to change the global default to 1s which I think would
be fine, but didn't want to break anything too badly.
2021-12-28 13:31:42 -06:00
Matthew Jaffee
fe54cbf8ae remove other print and tweak backup test timings 2021-12-28 13:31:42 -06:00
Matthew Jaffee
bb39b05d05 remove leftover fmt.Println 2021-12-28 13:31:42 -06:00
Hoang Pham
936fb9e6bd UI - rename a unit test 2021-12-28 13:04:56 -06:00
Ben Johnson
f8e13f9629
Merge pull request #1829 from molecula/metrics
Add job & worker metrics
2021-12-28 11:31:13 -07:00
Ben Johnson
310584b0d8 Add job & worker metrics 2021-12-28 10:01:18 -07:00
Hoang Pham
0ad2bffd33 UI - added test files 2021-12-28 10:56:31 -06:00
Samir Patel
e5fa99a531 apply mw to handlers 2021-12-28 10:08:44 -05:00
Samir Patel
6d590581d4 apply mw to handlers 2021-12-28 10:06:40 -05:00
Samir Patel
7544e7d1cb extend mw 2021-12-28 09:24:46 -05:00
Samir Patel
b9961870c1 implement as mw 2021-12-27 18:22:53 -05:00
Samir Patel
7a6595d628 authorize few endpoints e.g. query 2021-12-27 16:43:47 -05:00
Samir Patel
0ef67fd699 move query logger option to auth 2021-12-27 16:42:13 -05:00
Travis Turner
145f65ab0e
Merge pull request #1827 from molecula/tlt/etcd-data-dir
[FB-1125] Expose `etcd.dir` configuration option
2021-12-27 11:42:59 -06:00
Travis
6638fa17ee
Expose etcd.dir configuration option
The goal is to allow a user to separate FeatureBase and etcd I/O.
2021-12-27 11:13:38 -06:00
Ben Johnson
4a5179f87f
Merge pull request #1824 from molecula/rbf-expvar 2021-12-27 10:02:37 -07:00
Ben Johnson
9367a62609 Add /debug/rbf endpoint for debugging 2021-12-27 09:34:43 -07:00
Samir Patel
49e9faa03b stub out checker 2021-12-22 16:49:43 -06:00
Samir Patel
684c408b93 Merge branch '54mir/protect-endpoints' into queryLoggerSetup 2021-12-22 15:12:31 -06:00
Samir Patel
9bf56188f7 Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-22 14:08:21 -06:00
Samir Patel
8b40c6bf7b rm comments 2021-12-22 13:47:16 -06:00
Samir Patel
448289d609 add subcommand for key generation 2021-12-22 13:04:00 -06:00
Matthew Jaffee
f1b525fc74
Merge pull request #1807 from molecula/backup-http-retry
add exponential retry logic to internal http client, use in backup and restore
2021-12-22 13:00:24 -06:00
Matthew Jaffee
295fab4892 retry on >= 400, not just greater. good catch 2021-12-22 12:21:11 -06:00
Samir Patel
23a884b3a2 Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-22 12:05:41 -06:00
Samir Patel
b8b4425d4f clean up 2021-12-22 12:05:24 -06:00
Hoang Pham
39ebbbd88e UI - formatted tsx files with prettier (single quote) 2021-12-22 11:40:01 -06:00
Samir Patel
9612096682 Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-22 11:31:56 -06:00
Samir Patel
52d941d127 more tests 2021-12-22 11:31:37 -06:00
Matthew Jaffee
ea59f14d50 must use retryablehttp.NewClient to get defaults
otherwise it won't actually retry :(
2021-12-22 11:21:11 -06:00
Matthew Jaffee
640ba45129 use retryableHTTP in client, fix memory usage of restore
instead of awkwardly reading an entire file into a buffer, we use
retryablehttp's reader func to open the file fresh if we need to
retry, so a small fixed-size buffer can be used internally for copying
the contents onto the network.
2021-12-22 10:56:16 -06:00
Seebs
63d8686e22 scratch space -- need to finish updating deployPerf though 2021-12-21 16:20:25 -07:00
Seebs
b4304765e8 partial draft of perf/regression test script 2021-12-21 16:20:25 -07:00
Hoang Pham
c67ae54b1d UI - fixed Sign In button 2021-12-21 16:44:27 -06:00
Matthew Jaffee
cde3f6b5ea add profiling to backup/restore 2021-12-21 16:24:21 -06:00
Matthew Jaffee
2bce396445 add retry restore test and custom retry policy 2021-12-21 16:24:21 -06:00
Matthew Jaffee
d3b9193c8d try to fix data race with http lib
WARNING: DATA RACE
Write at 0x00c008121e80 by goroutine 235:
  bytes.(*Reader).WriteTo()
      /usr/local/go/src/bytes/reader.go:139 +0x45
  github.com/molecula/featurebase/v2/http.nopCloser.WriteTo()
      <autogenerated>:1 +0x5d
  io.copyBuffer()
      /usr/local/go/src/io/io.go:391 +0x482
  io.Copy()
      /usr/local/go/src/io/io.go:368 +0x78
  net/http.(*transferWriter).doBodyCopy()
      /usr/local/go/src/net/http/transfer.go:400 +0x2f
  net/http.(*transferWriter).writeBody()
      /usr/local/go/src/net/http/transfer.go:364 +0xc9a
  net/http.(*Request).write()
      /usr/local/go/src/net/http/request.go:682 +0x887
  net/http.(*persistConn).writeLoop()
      /usr/local/go/src/net/http/transport.go:2343 +0x349

Previous write at 0x00c008121e80 by goroutine 192:
  bytes.(*Reader).Seek()
      /usr/local/go/src/bytes/reader.go:118 +0x824
  github.com/molecula/featurebase/v2/http.(*InternalClient).doWithRetry()
      /go/src/github.com/molecula/featurebase/http/client.go:1773 +0x86d
  github.com/molecula/featurebase/v2/http.(*InternalClient).executeRequest()
      /go/src/github.com/molecula/featurebase/http/client.go:1806 +0x15b
  github.com/molecula/featurebase/v2/http.(*InternalClient).CreateIndex()
      /go/src/github.com/molecula/featurebase/http/client.go:433 +0xbf8
  github.com/molecula/featurebase/v2/server_test.TestMain_Set_Quick.func1()
      /go/src/github.com/molecula/featurebase/server/server_test.go:64 +0x624
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1123 +0x202

Goroutine 235 (running) created at:
  net/http.(*Transport).dialConn()
      /usr/local/go/src/net/http/transport.go:1709 +0xc30
  net/http.(*Transport).dialConnFor()
      /usr/local/go/src/net/http/transport.go:1421 +0x151

Goroutine 192 (running) created at:
  testing.(*T).Run()
      /usr/local/go/src/testing/testing.go:1168 +0x5bb
  github.com/molecula/featurebase/v2/server_test.TestMain_Set_Quick()
      /go/src/github.com/molecula/featurebase/server/server_test.go:45 +0x116
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1123 +0x202
2021-12-21 16:24:21 -06:00
Matthew Jaffee
f676fbfc51 add retryability to restore command 2021-12-21 16:24:20 -06:00
Matthew Jaffee
3105a24542 rewind Body on retry
this is really not ideal, and there are libraries for this kind of
thing, but I'd have to figure out how to make the libraries work with
everywhere we're already creating stdlib http clients.
2021-12-21 16:24:20 -06:00
Matthew Jaffee
cdf4bc4c88 add clustertests testing backup's retry 2021-12-21 16:24:20 -06:00
Matthew Jaffee
8486efaa79 add exponential retry logic to internal http client, use in backup 2021-12-21 16:24:20 -06:00
Hoang Pham
2bf1f0e4d4 Merge branch '54mir/authentication' of ssh://github.com/molecula/featurebase into 54mir/authentication 2021-12-21 16:06:11 -06:00
Hoang Pham
7de6c37b11 UI - cleaned up code, added comments 2021-12-21 16:06:02 -06:00
rachithrr
5650a24c9b query logger is set up. 2021-12-21 16:52:22 -05:00
Garrison Davis
d9dc613dd5
Merge pull request #1820 from molecula/pipeline-changes
Run integration on merge to default branch
2021-12-21 14:50:29 -07:00
Samir Patel
fd7d905be2 fix formatting issues 2021-12-21 15:49:51 -06:00
garrison.davis@molecula.com
15612b8b92 Run integration on merge to default branch
Additionally, the go version is using the GOVERSION build
variable instead.
2021-12-21 13:58:10 -07:00
Samir Patel
f011587d4e add tests 2021-12-21 10:08:49 -06:00
Samir Patel
1c907281bf authz changes 2021-12-20 18:03:18 -06:00
Samir Patel
10a7aa55ea same-site strict 2021-12-20 18:00:13 -06:00
Samir Patel
d9710cb7d7 remove auth struct from authorization 2021-12-20 16:45:17 -06:00
Samir Patel
3b374a62bf Merge branch 'master' into 54mir/authentication 2021-12-20 16:42:11 -06:00
Hoang Pham
a24a1e8922 UI - added fixes for PR comments 2021-12-20 15:55:52 -06:00
Samir Patel
602145b390 add to tests 2021-12-20 15:41:18 -06:00
Matthew Jaffee
18d2ef3d53
Merge pull request #1818 from molecula/fb1107
[FB-1107] slightly better lock protection around bitDepth in view
2021-12-20 15:31:13 -06:00
Seebs
ddb5020aa6 slightly better lock protection around bitDepth in view
There's a number of deeper issues here (the fragment is conjuring
up a Tx, for instance) but this helps.

Also use field.view() to get the view rather than accessing viewMap
directly without a lock. Also change field.cacheBitDepth to ratchet
upwards -- if we have multiple shards and some shards have lower
depths than others, we should use the highest as the cached value,
not the most recent.
2021-12-20 15:09:27 -06:00
Ben Johnson
3c082b7d2c
Merge pull request #1819 from molecula/rbf-check-empty-branch
[FB-1105] Add rbf check for empty branch pages
2021-12-20 14:01:10 -07:00
Ben Johnson
60f0008dec
Merge branch 'master' into rbf-check-empty-branch 2021-12-20 13:40:34 -07:00
Samir Patel
6faa889bfb move logout url to conf 2021-12-20 14:30:19 -06:00
Ben Johnson
6481b4eabe Add rbf check for empty branch pages 2021-12-20 13:24:34 -07:00
Matthew Jaffee
3de18a9f77
Merge pull request #1816 from molecula/fb-1105
[FB-1105] Fix RBF multi-level branch delete
2021-12-20 14:13:24 -06:00
Ben Johnson
5f8a281918 Fix RBF multi-level branch delete
This commit fixes a bug in RBF where deleting all the elements in
a bitmap that has a depth greater than 2 will cause the root bitmap
to be a branch page with a cell count of zero. This breaks an
assertion in `readBranchCell()` which causes a panic post-commit.

A new assertion has been added to prevent a branch page from being
written with a zero count in the future.
2021-12-20 12:52:14 -07:00
Samir Patel
405692e376 Update authn/authenticate_test.go
Co-authored-by: souhailanoor <90720110+souhailanoor@users.noreply.github.com>
2021-12-20 13:16:34 -06:00
souhailanoor
7d0e0600d6
Merge pull request #1805 from molecula/fb1000
FB-1000: Ability to map user groups to cluster admin / index-level permissions
2021-12-20 13:07:13 -06:00
souhailanoor
55c67a9d1f
Merge branch 'master' into fb1000 2021-12-20 12:35:17 -06:00
seebs
88569789dd
Merge pull request #1817 from molecula/pages
rbf pages subcommand: don't panic on invalid page type
2021-12-20 12:30:57 -06:00
Hoang Pham
fa96d39cd0 Merge branch '54mir/authentication' of ssh://github.com/molecula/featurebase into 54mir/authentication 2021-12-20 12:30:27 -06:00
Hoang Pham
c91e7dc8de UI - renamed authOn to isAuthOn 2021-12-20 12:28:38 -06:00
Samir Patel
89f360c1ce Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-20 12:28:26 -06:00
Samir Patel
e7f4eb1e36 response codes 2021-12-20 12:28:17 -06:00
Hoang Pham
7dc9df425d UI - removed unnecessary code 2021-12-20 12:23:55 -06:00
Hoang Pham
9086587e06 Changed how the UI processes /auth to turn on/off authentication 2021-12-20 12:19:56 -06:00
Seebs
977a699a98 don't panic on invalid page type
debugging tools shouldn't panic when they encounter bugs. insert
"you had one job" meme.
2021-12-20 10:58:41 -06:00
Hoang Pham
d7ba3c8334 UI - changed createTheme back to createMuiTheme 2021-12-20 09:57:07 -06:00
Samir Patel
daeebf98eb more test cleanup 2021-12-20 09:43:30 -06:00
Samir Patel
67d438aab5 clean up 2021-12-20 01:29:11 -06:00
Samir Patel
605d47702e add handler tests 2021-12-20 00:15:48 -06:00
Samir Patel
4b4095f13e Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-19 23:35:07 -06:00
Samir Patel
0d52a952e0 resolve some comments 2021-12-19 23:33:44 -06:00
souhailanoor
e82088e086
Merge branch 'master' into fb1000 2021-12-19 11:38:08 -06:00
Souhaila Noor
c14bd08213 updated admin to be at the cluster level 2021-12-19 11:37:41 -06:00
Ben Johnson
06204bcf7b
Merge pull request #1809 from molecula/fb992
[FB-992] Implement RBF Async Checkpoint
2021-12-18 13:08:42 -07:00
Matthew Jaffee
7826c06eee use atomics for currentWorker to avoid race 2021-12-18 09:04:04 -06:00
Seebs
8974014d57 too tired to be writing code 2021-12-17 22:48:40 -06:00
Seebs
1439c316d3 read-only lock for check of shutdown 2021-12-17 22:25:01 -06:00
Seebs
9a2a8f964c fix silly typo in worker pool downscaling 2021-12-17 22:22:27 -06:00
Seebs
8f217ab099 scale down worker pool when it's large
if we have more than twice our starting worker pool, and have had no
tasks when checking the queue for multiple rounds, send a job telling
the system to retire a worker. eventually we'll get down to about 2x
the starting pool size if we stay idle.
2021-12-17 22:05:41 -06:00
Seebs
9945575bf1 create a new worker every so often if progress isn't happening
this is very approximate and may be a mess and may be unbounded, but
in practice i think it should be okay. if it's not we'll have an
adventure.
2021-12-17 21:57:38 -06:00
Hoang Pham
89a628e91a Added Featurebase UI code for authentication 2021-12-17 18:20:20 -06:00
Seebs
41f6156bda don't use write Tx even when we're using the expensive logic for write Tx 2021-12-17 17:57:33 -06:00
Souhaila Noor
a606bd030a addressed reviewer's feedback 2021-12-17 16:46:07 -06:00
Souhaila Noor
f05f1d0de2 added more authz functionality 2021-12-17 15:51:37 -06:00
Matthew Jaffee
0799862266 move some locks, nbd 2021-12-17 15:09:25 -06:00
Matthew Jaffee
1fd872b126 less write locks in fragment.importRoaring/row 2021-12-17 15:09:25 -06:00
Ben Johnson
57ca5591a2 Unlock rbf.DB during WAL copy & fsync() 2021-12-17 15:09:25 -06:00
Seebs
47e098c3b1 simplify txWaiter
We don't need a condition variable for a thing with a single waiter
which waits only once, and a data structure which only one side ever
modifies. That's a closable channel.
2021-12-17 15:09:25 -06:00
Seebs
994cc03e88 fix locking and list management for afterCurrentTx
Two issues: First, there was a race condition because we were never
using the mutex for anything but the condvar broadcast, second, there
was no reason for the afterCurrentTx to need to maintain the list since
we already know where in the list we are when we are waking it up.

afterCurrentTx still wants to run with the db lock held, because
the degenerate case (no outstanding Tx) means that it will be running
with it held already. That's for another commit.
2021-12-17 15:09:25 -06:00
Seebs
5764d98f6d test fixes and order of operations on changing db.PageMap
We need to update db.PageMap after we write the db, but before
we truncate the WAL, so new transactions don't pick up the old
PageMap and then get a truncated WAL.

Also, checkpoint should not abort if there's txs -- that's okay now.
2021-12-17 15:09:25 -06:00
Seebs
29f5f6d7c2 copy things rows after getting them and before their finishers during writes
When a qcx is a write, every Tx under it closes immediately, thus
invalidating all returned data. Thus, if you do a Not() inside a Store(),
you're doing a difference on an existence row and some other row
call... and both of those rows were run, individually, as separate
transactions that got invalidated the moment they were fetched. Oops.
2021-12-17 15:09:25 -06:00
Ben Johnson
4279e2cb2d rebase fixes 2021-12-17 15:09:25 -06:00
Seebs
c3c02eabb0 almost but not quite support async checkpoint
This gets us to being able to run reads during a checkpoint, but
now we have to wait for new reads to end before we can release
the write lock, etc.

This is actually slightly slower, but if we could get ONE more step,
we could allow new writes during that phase, to a different WAL,
if we had a different WAL to write to.
2021-12-17 15:09:25 -06:00
Seebs
6d68e71933 make the checkpoint async 2021-12-17 15:09:25 -06:00
Seebs
806669fa0f make db able to fail out if it can't checkpoint, fix silly wrong-units error
PageMap uses "WALID", which is a WAL page ID relative to the "base" ID of the
WAL, rather than the wal page count you'd get just reading the file. So everything
it reports has a fixed offset at any given time. I think this may be left
over from a point where there were partial checkpoints. Anyway, the net
outcome is that each new transaction was getting different page IDs, but
the actual WAL pages did not always reflect that. Each checkpoint increases
the offset. This might imply that we can start having problems after
4 billion pages written even if most of them were redundant?

Anyway, with that fixed, this seems to work. I think.
2021-12-17 15:09:25 -06:00
Seebs
b8f59d922c checkpoint rework/refactoring: logger, async-ish checkpoint
Trying to make the checkpoint be asynchronous-at-all, and
also allowing it to log.
2021-12-17 15:09:25 -06:00
Seebs
a631e25dc5 refactor: removeTx responsible for getting/releasing its own lock
We change nothing substantive here, except that there's a window
between when a write transaction updates the root pages and when
it removes itself from the db tx list and possibly causes a checkpoint
where it's not holding the db lock.

The issue here is that we want to be able to *keep* the lock but
still return, so no one else can start transactions, but the specific
Rollback or Commit that removed the last outstanding transaction
doesn't block forever. This will, later, allow us to exercise
finer-grained control over when we allow transactions. This is
a separate commit so we can run the test suite against it, and
verify that this part in particular didn't break anything.
2021-12-17 15:09:25 -06:00
Seebs
5c889c72bd make test hit the lock harder
Discovered test was running slightly strange and spending an unreasonable
amount of time on rand.Intn(), possibly because we weren't caching the
value used as the loop condition. Tweaked that, also made the pool a
bit different. Now it takes ~50 seconds for benchtime 100x, and produces
a profile with a TON of time spent waiting on sleeps (expected) and
the condition variable for waiting on checkpoints (the thing we want
to measure, really).
2021-12-17 15:09:25 -06:00
Seebs
3ed4487ae2 scratch space for FB-992: create benchmark for checkpointing
Note also the commented-out debug printf in checkpoint, there as a
reference. This is interesting because it turns out that MOST of checkpoint
writes is not actually writing new pages in most cases.

The actual "pages in WAL : pages in map" ratio is typically around 30:1
apparently. This would likely be different in cases where we were
updating existing data, though.

This is scratch space to prep for an actual work. The final
results will likely be different.
2021-12-17 15:09:25 -06:00
souhailanoor
44b855d50b
Merge branch 'master' into fb1000 2021-12-17 11:46:25 -06:00
Souhaila Noor
2ca29e6018 addressed reviewer's comments and added more tests 2021-12-17 11:45:35 -06:00
Samir Patel
7ce07d4e4a settings 2021-12-17 11:42:02 -06:00
Samir Patel
3b58e887ed add group lenth check 2021-12-17 11:34:48 -06:00
Samir Patel
c2d51a2257 remove settings 2021-12-17 10:00:21 -06:00
Samir Patel
1555746ff1 test 2021-12-16 23:53:30 -06:00
Samir Patel
db2263465b tests 2021-12-16 23:39:58 -06:00
Samir Patel
e5866f5f9c comment out string checking in test 2021-12-16 22:08:16 -06:00
Samir Patel
a793ebc3c4 update config internal test 2021-12-16 21:56:54 -06:00
Samir Patel
4565cb714b update config internal test 2021-12-16 21:02:58 -06:00
Samir Patel
eb693beb0b add authN login test 2021-12-16 20:35:34 -06:00
Samir Patel
b082a318f3 move authN to its own package 2021-12-16 20:34:09 -06:00
Samir Patel
b37f13e5c5 rename 2021-12-16 20:33:23 -06:00
reese
65ab92f364
Merge pull request #1811 from molecula/fb-1027
[fb-1027] ensure field bit depth is set when restoring shard
2021-12-16 08:54:34 -06:00
reesporte
c59ce837b3 ensure field bit depth is set when restoring shard
we have to manually set the cache value here bc it wont get set until the node is restarted otherwise
2021-12-15 16:09:45 -06:00
Samir Patel
52625c70ab check auth enabled before handling auth requests 2021-12-15 15:42:56 -06:00
Samir Patel
0cb27bfdd3 Merge branch '54mir/authentication' of github.com:molecula/featurebase into 54mir/authentication 2021-12-15 14:54:41 -06:00
Samir Patel
10dbbb49c8 rename 2021-12-15 14:54:01 -06:00
Samir Patel
f0e287e40b handle logout and userinfo 2021-12-15 14:53:30 -06:00
Samir Patel
a1de086cd8 change scopes from string to slicee 2021-12-15 14:53:04 -06:00
Samir Patel
1bd935bb59 separate out authentication from auth 2021-12-15 14:52:16 -06:00
Samir Patel
213572bb78 add logout and userinfo endpoints 2021-12-15 14:51:45 -06:00
Souhaila Noor
484cbbcd09 fixed func name 2021-12-15 14:19:21 -06:00
souhailanoor
0c65485b0e
Merge branch 'master' into fb1000 2021-12-15 13:37:15 -06:00
Souhaila Noor
48913caafd renamed package to authz, inmplemented reviewer's feedback 2021-12-15 13:36:27 -06:00
Samir Patel
7d81c6e1c1 add defaults to conf 2021-12-15 12:39:14 -06:00
Matthew Jaffee
600494c724
Merge pull request #1810 from molecula/sup-126
[SUP-126] Defer unlock & rollback during rbf.DB.Begin()
2021-12-15 08:39:24 -06:00
Ben Johnson
7141662c03 Defer unlock & rollback during rbf.DB.Begin() 2021-12-15 07:16:30 -07:00
Samir Patel
a261aa9972 refactor auth.go 2021-12-13 23:13:19 -06:00
Samir Patel
4eee8a4245 change the way auth is instantiated, and send to handler 2021-12-13 23:12:04 -06:00
Samir Patel
541132a176 hash and block key cmd options 2021-12-13 23:10:29 -06:00
Samir Patel
bd81427dd5 load auth object into handler 2021-12-13 23:10:04 -06:00
Samir Patel
ee9416d53a move auth struct to config 2021-12-13 23:09:14 -06:00
Samir Patel
5e6aec6f60 add hash and block keys to conf file 2021-12-13 23:08:41 -06:00
souhailanoor
a8b198af99
Merge branch 'master' into fb1000 2021-12-13 14:15:09 -06:00
Hoang Pham
583a0293ce added Login page for testing with BE endpoint 2021-12-13 14:04:41 -06:00
tgruben
a52eda0510
Merge pull request #1808 from molecula/sup120
[SUP-120] use higher level iterator in order to account for ops log
2021-12-13 13:51:29 -06:00
Todd Gruben
c25ab78b03 use higherlevel iterator in order to account for ops log 2021-12-13 13:10:16 -06:00
Souhaila Noor
3c8a7384ba added reviewer's suggestions 2021-12-13 13:05:35 -06:00
Souhaila Noor
32228bb134 updated go.mod 2021-12-13 10:48:40 -06:00
Souhaila Noor
9e2cf81127 added unit tests 2021-12-13 10:35:56 -06:00
Samir Patel
3b257fe3cb remove settings 2021-12-11 14:10:34 -06:00
Samir Patel
b5c87e0f18 add auth endpoints 2021-12-11 00:11:30 -06:00
Samir Patel
29832a3140 add authorization 2021-12-10 16:45:20 -06:00
Matthew Jaffee
7935624549 implement percentiles on timestamp/decimal, still needs tests 2021-12-10 15:21:29 -06:00
souhailanoor
e5052a864b
Merge branch 'master' into fb1000 2021-12-10 14:09:39 -06:00
Souhaila Noor
01e4baab04 determine permission for user access to index 2021-12-10 14:07:24 -06:00
Matthew Jaffee
9283d52141
Merge pull request #1798 from molecula/fix-backup-key-translation
FB-1080 Fix backup key translation
2021-12-10 13:59:43 -06:00
Matthew Jaffee
e8972e437e smaller clusters to take less memory... test-race getting oom killed 2021-12-10 11:52:39 -06:00
Matthew Jaffee
081184f436 another data race? fuck 2021-12-10 11:52:39 -06:00
Matthew Jaffee
f2a6ee738c remove old shell-based backup/restore tests 2021-12-10 11:52:39 -06:00
Matthew Jaffee
53373240ef make chksum process All() results correctly for unkeyed indexes 2021-12-10 11:52:39 -06:00
Matthew Jaffee
ea267202bd more complete backup/restore coverage in go tests
I think we can remove the shell version now
2021-12-10 11:52:39 -06:00
Matthew Jaffee
1980c8b8e5 featurebase backup: don't hide TranslateStoreNotFoundError
I think this shouldn't happen unless there's actually a problem
2021-12-10 11:52:39 -06:00
Matthew Jaffee
b0d29bb425 fix unrelated data race that randomly cropped up in CI 2021-12-10 11:52:39 -06:00
Matthew Jaffee
3d3080df8b full backup/restore test in a Go test 2021-12-10 11:52:39 -06:00
Matthew Jaffee
aff3d3ddd9 do a backup in a go test for coverage purposes
also found a weird issue with schema marshalling

if you create a field thru the api w/o specifying a field type, you
get slightly different behavior than going thru the HTTP handler which
is... not ideal. I changed the marshaler to accept an empty field type.
2021-12-10 11:52:39 -06:00
Matthew Jaffee
3761fc6d3c have Circle build release on branch instead of waiting for merge 2021-12-10 11:52:39 -06:00
Matthew Jaffee
7a8f0135b3 redirect GetTranslateData if node doesn't own partition 2021-12-10 11:52:39 -06:00
Matthew Jaffee
b8da3bc7e6 checksum All() instead of Count(All()) to cover index keys 2021-12-10 11:52:39 -06:00
reese
e45a26cc19
Merge pull request #1804 from molecula/copyright-notice-added-back-in
[no-000] add copyright notice back in
2021-12-10 11:21:03 -06:00
reesporte
48aef0c8a4 add copyright notice back in
```bash
for file in `cat diffys`; do
   printf '%s\n%s\n' "// Copyright 2021 Molecula Corp. All rights reserved." "$(cat $file)" >$file;
done
```
2021-12-10 11:01:04 -06:00
reese
eca56c52d4
Merge pull request #1803 from molecula/no-license
[no-000] removed license from each go file
2021-12-10 10:06:43 -06:00
reesporte
4c53f86e82 removed license from each go file
i used this script, a little clunky but it got the job done

```bash
for file in `find . -type f -print | grep '\.go'`; do
    sed '1,/^\/\/ limitations under the License.$/d' $file > $file.tmp;
    result=`cat $file.tmp`
    if [[ result != "" ]]; then
        gofmt $file.tmp &> /dev/null;
        if [[ $? == 0 ]]; then
            mv $file.tmp $file && gofmt -w $file;
        else
            rm $file.tmp;
        fi
    else
        rm $file.tmp;
    fi
done
```
2021-12-10 09:17:17 -06:00
reese
0f51a85002
Merge pull request #1802 from molecula/sup120-pt1
[FB-1092] translaste -> translate
2021-12-09 09:09:45 -06:00
reesporte
76c1d237ac translaste -> translate
also remove meaingless comments
2021-12-08 16:35:26 -06:00
Matthew Jaffee
6dbbb52438
Merge pull request #1801 from molecula/simplify-coverage
try to simplify test coverage w/ -coverpkg
2021-12-08 13:46:51 -06:00
Matthew Jaffee
4f55f423b0
Merge branch 'master' into simplify-coverage 2021-12-08 12:57:31 -06:00
reese
134cc8c2e3
Merge pull request #1800 from molecula/sup112
[SUP-112] Roaring-migrate panic bug fix
2021-12-08 10:55:35 -06:00
Matthew Jaffee
c91e81537d try something a bit different 2021-12-08 09:54:20 -06:00
reesporte
69f364e167 remove breaking test 2021-12-08 09:30:16 -06:00
reesporte
a2b86caad8 Merge branch 'master' into sup112 2021-12-08 09:24:02 -06:00
reesporte
47f78c88e0 check that translate store is not nil where it needs to be checked 2021-12-08 09:23:46 -06:00
reesporte
fed20ffd3e test that translate key error messages are correct 2021-12-08 09:23:46 -06:00
Matthew Jaffee
a40bc3edf7 try to simplify test coverage w/ -coverpkg 2021-12-07 18:38:48 -06:00
reesporte
f223d2d84b Merge branch 'sup112-with-tests' into sup112 2021-12-07 15:21:14 -06:00
Matthew Jaffee
4488ab1062
Merge pull request #1784 from molecula/recordbatch-ingestapi
add new RecordBatch implementation which uses ingest API
2021-12-06 20:40:09 -06:00
Matthew Jaffee
77897f3ef0 try to get some more test coverage on error cases
(without creating too much duplication!)
2021-12-06 20:19:42 -06:00
Matthew Jaffee
1a4180ca4a add new RecordBatch implementation which uses ingest API 2021-12-06 17:06:55 -06:00
reese
7788af166f
Merge pull request #1797 from molecula/staticcheck-issues-pt-2
[fb-964] fixes some more staticcheck errors
2021-12-06 17:04:35 -06:00
reesporte
a0aaa0f371 don't start error messages with a capital letter 2021-12-06 16:40:13 -06:00
reesporte
0a82474a65 Merge branch 'master' into staticcheck-issues-pt-2 2021-12-06 16:33:25 -06:00
reese
8cd9dcd70d
Merge pull request #1799 from molecula/distinct-timestamp-count
[FB-1081] fix count on distinctTimestamp
2021-12-06 16:28:38 -06:00
reesporte
716a3a89c1 added test case 2021-12-06 16:16:43 -06:00
reesporte
060c73fb2f add some tests for the encoding/decoding of DistinctTimestamp 2021-12-06 15:35:39 -06:00
reesporte
af3c5809e2 add support for multi-node queries 2021-12-06 14:57:05 -06:00
reesporte
4f03228968 fix count on distinctTimestamp
adds the ability to get the count of a distinct call to a timestamp field
2021-12-06 11:57:17 -06:00
reesporte
4c9029e0b6 Merge branch 'master' into sup112 2021-12-06 10:43:52 -06:00
reese
6ae433efbd
Merge branch 'master' into staticcheck-issues-pt-2 2021-12-06 09:11:59 -06:00
Matthew Jaffee
a8b1b93fa7
Merge pull request #1795 from molecula/topk-on-mutex
FB-1079 enable TopK on mutex fields
2021-12-03 17:15:40 -06:00
reesporte
b046ad5e8f fixes some more staticcheck errors 2021-12-03 16:50:02 -06:00
Matthew Jaffee
bd3e73ba66 refactor test to reduce duplication
I guess this is actually better... thanks SonarCloud!
2021-12-03 16:41:49 -06:00
Matthew Jaffee
58b4f40cdc enable TopK on mutex fields
I think it was just an oversight that it wasn't, because this seems to work
2021-12-03 16:41:49 -06:00
reese
d47cf8d3de
Merge pull request #1758 from molecula/staticcheck-issues
[FB-964] resolve some more staticcheck issues
2021-12-03 16:39:20 -06:00
reese
3d3d0b7a51
Merge branch 'master' into staticcheck-issues 2021-12-03 16:02:30 -06:00
reese
f4a2960a11
Merge pull request #1796 from molecula/pilosa-rename
[FB-1021] rename to pilosa
2021-12-03 15:28:54 -06:00
reesporte
c2964f7c7b rename to pilosa
thanks to alan's comment [here](https://molecula.atlassian.net/browse/FB-1021?focusedCommentId=11721)
2021-12-03 14:56:18 -06:00
reese
30b45adb30
Merge branch 'master' into staticcheck-issues 2021-12-03 14:28:44 -06:00
souhailanoor
ad5b3da9f9
Merge pull request #1793 from molecula/fb1031-souhaila
FB-1031: Update featurebase.conf to enable configuring an arbitrary OAuth2.0 provider as the Identity Provider for FB AuthN/AuthZ
2021-12-03 13:42:13 -06:00
reese
47d70f1aa9
Merge branch 'master' into staticcheck-issues 2021-12-03 13:34:27 -06:00
souhailanoor
2a2e272093
Merge branch 'master' into fb1031-souhaila 2021-12-03 13:00:36 -06:00
seebs
b3270c61eb
Merge pull request #1791 from molecula/sup119
FB-1073:  handle errors more gracefully, but don't stream CreateKeys
2021-12-03 13:00:23 -06:00
Souhaila Noor
7bcbb5eaca fixed indentation 2021-12-03 12:10:31 -06:00
Souhaila Noor
90c3c67ce4 fixed test for auth disabled 2021-12-03 12:00:07 -06:00
souhailanoor
e8f5458100
only validate config when auth is enabled
Co-authored-by: reese <45641995+reesporte@users.noreply.github.com>
2021-12-03 11:58:08 -06:00
souhailanoor
cebba84bee
add scope to install/featurebase.conf
Co-authored-by: Samir Patel <48686912+54mir@users.noreply.github.com>
2021-12-03 11:38:43 -06:00
Souhaila Noor
6425fc50fc added identity provider scope url as parameter 2021-12-03 11:24:18 -06:00
Souhaila Noor
8bf7f58961 Merge branch 'master' into fb1031-souhaila 2021-12-03 10:59:57 -06:00
Souhaila Noor
06fd65cb31 resolved reviewer's suggestions and made it pretty & user friendly 2021-12-03 10:56:21 -06:00
tgruben
da1cc34f96
Merge branch 'master' into sup119 2021-12-03 10:55:38 -06:00
reesporte
666baffb7d Merge branch 'master' into staticcheck-issues 2021-12-03 09:36:13 -06:00
reesporte
63c5c11108 fix some staticcheck issues 2021-12-03 09:31:45 -06:00
tgruben
f17d6b836e
Merge pull request #1792 from molecula/store-fix
[FB-1041] Handle bitmap page recycling properly
2021-12-02 17:11:42 -06:00
Souhaila Noor
978f236c59 resolved additional comments 2021-12-02 16:36:04 -06:00
Souhaila Noor
78e11e0fda resolved reviewer's comments 2021-12-02 16:15:15 -06:00
tgruben
3e5877299b
Merge branch 'master' into store-fix 2021-12-02 16:00:53 -06:00
Todd Gruben
1df90af26e free bitmap pages on deallocate 2021-12-02 15:57:52 -06:00
reesporte
5ab83243c6 add tests checking for the proper errors on nil results 2021-12-02 15:47:49 -06:00
Souhaila Noor
50d80f2f1c fixed arg cli descriptions 2021-12-02 14:52:38 -06:00
Souhaila Noor
aebd4c4c62 fixed formatting 2021-12-02 14:22:08 -06:00
Souhaila Noor
7de3eaa935 resolved review's comment 2021-12-02 14:19:59 -06:00
Souhaila Noor
91c8bf5e05 fixed duplicated empty string 2021-12-02 14:04:21 -06:00
Souhaila Noor
214a6dfac4 Merge branch 'fb1031-souhaila' of github.com:molecula/featurebase into fb1031-souhaila 2021-12-02 14:01:06 -06:00
Souhaila Noor
64b31da4a1 resolved duplicated line 2021-12-02 14:00:51 -06:00
souhailanoor
0189b2eef7
Merge branch 'master' into fb1031-souhaila 2021-12-02 13:11:19 -06:00
Souhaila Noor
b5ba3fb2ea added auth arg validation and set up auth package 2021-12-02 13:09:13 -06:00
Seebs
7270016d1a don't explode on translate data restore for _keys
There isn't really a field called _keys but some old backups
will think they have translate data for this. Ignore it politely.

Also in general produce a diagnostic rather than a panic for
translate data restores to nonexistent indexes or fields.
2021-12-01 12:04:24 -06:00
Seebs
8b20406f45 experiment: handle errors more gracefully, but don't stream CreateKeys
We were trying to write an error to a ResponseWriter After attempting to
write to it, and this produces messages about superfluous WriteHeaders,
which is correct. This patch changes things so that we report messages
more clearly and verbosely if we hit them before writing, and if we try
to write and fail, we log the message because that's all we can do.

This does change semantics slightly, in that now we're marshalling
separately from trying to write the marshalled data. I think this is
probably a reasonable call because it lets us get diagnostics about a
hypothetical encoding problem, but in practice I don't think there
should be any encoding problems. So my guess is the actual error will
occur in that last line, and be logged to the server console instead
of failing to write over HTTP.

Also note that this changes some of the messages to include the
underlying error they're complaining about.

We also merge the create/find and index/field cases because only a
couple of lines of code changed between four largeish functions,
and we test some of the failure cases.

We don't have test coverage on the "field isn't provided" type things
because the mux won't actually route things there without them, so
far as I know.
2021-12-01 11:06:54 -06:00
tgruben
73f3c01284
Merge pull request #1790 from molecula/tgruben-patch-1 2021-11-30 21:34:27 -06:00
tgruben
740f3e2838
Merge branch 'master' into tgruben-patch-1 2021-11-30 18:48:41 -06:00
Souhaila Noor
dc1c39fd21 updated featurebase.conf 2021-11-29 16:46:55 -06:00
seebs
21f2868175
Merge pull request #1785 from molecula/sanitycheck
Perform sanity check only if we have the storage it runs on
2021-11-29 09:58:55 -06:00
Souhaila Noor
28e1be7540 added AuthN/AuthZ parameters to featurebase server configuration 2021-11-29 09:40:05 -06:00
tgruben
8b7d429417
Update README.md 2021-11-29 09:18:44 -06:00
souhailanoor
0bcac33313
Merge branch 'master' into sanitycheck 2021-11-24 08:31:13 -06:00
souhailanoor
42f3b79640
Merge pull request #1786 from molecula/fixBugInCicdPipeline
remove duplicate code in multiple stages of gitlab yml for CICD
2021-11-24 08:30:54 -06:00
Souhaila Noor
65c4fc9cdb updated error messages 2021-11-23 20:28:14 -06:00
Souhaila Noor
02b0f4ffd6 test standard condition 2021-11-23 18:50:47 -06:00
Souhaila Noor
0e2d71c303 added error handling 2021-11-23 18:48:06 -06:00
Souhaila Noor
6172f98eab test failed condition 2021-11-23 18:32:09 -06:00
Souhaila Noor
001678386f define ip var 2021-11-23 17:27:57 -06:00
Souhaila Noor
42b6c2b351 updated syntax 2021-11-23 17:25:10 -06:00
Souhaila Noor
afb96f4a9b pass error back to gitlab runner 2021-11-23 17:17:13 -06:00
Souhaila Noor
b243f4b8a3 fix yaml error 2021-11-23 17:10:13 -06:00
Souhaila Noor
d13eef4c4b echo errors 2021-11-23 17:09:35 -06:00
Souhaila Noor
612e11887f added dependency 2021-11-23 16:41:35 -06:00
Souhaila Noor
88c89749af updated job's stage 2021-11-23 16:37:11 -06:00
Souhaila Noor
f03720f0a3 error handling 2021-11-23 16:33:32 -06:00
Souhaila Noor
2de7d2c885 fixed yaml syntax error 2021-11-23 16:26:09 -06:00
Souhaila Noor
0030e759da removed aws config from shell script 2021-11-23 16:24:56 -06:00
Souhaila Noor
d781dfb29b remove error handling to debug 2021-11-23 16:18:14 -06:00
Souhaila Noor
8a77da0db9 removed ssh keys from shell script 2021-11-23 16:14:21 -06:00
Souhaila Noor
184b935550 added print statement 2021-11-23 16:07:22 -06:00
Souhaila Noor
53d7d6b91c fix for ssh-add error 2021-11-23 16:04:29 -06:00
Souhaila Noor
cceb173d5d added before script commands 2021-11-23 15:55:36 -06:00
Souhaila Noor
a6bc10dec9 removed single quotes 2021-11-23 15:50:43 -06:00
Souhaila Noor
dbd1e611d0 changed jobs order 2021-11-23 15:42:12 -06:00
Souhaila Noor
53766f47ca fixed jobs dependencies and added args 2021-11-23 15:38:09 -06:00
Souhaila Noor
aac3b0768c fixed syntax error 2021-11-23 15:32:22 -06:00
Souhaila Noor
97841608e0 switched stages to make testing faster 2021-11-23 15:26:42 -06:00
Souhaila Noor
cce48a2638 created a shell script for deplooying node and handling error conditions 2021-11-23 15:24:47 -06:00
Souhaila Noor
692f2f8cb4 updated dependency of jobs and made instanceId a global variable 2021-11-23 13:29:56 -06:00
Souhaila Noor
7e8cbdeb53 updated a comment to trigger the pipeline for another test 2021-11-23 12:09:51 -06:00
Souhaila Noor
fbf4463572 remove duplicate code in multiple stages 2021-11-23 11:08:14 -06:00
Seebs
14911bfdff Perform sanity check only if we have the storage it runs on
SanityCheckMapping is specific to roaring bitmaps stored in-memory, if
we have an RBF backend, we shouldn't even try it, it'll just panic.

This implies that, in whatever circumstance we were hitting this, we
were getting an error back from the backend. We still need to address
that error, but to do that we need to know what it was, which we don't
if we panic.
2021-11-23 10:22:06 -06:00
Kasey C. Rodgers
769a750cdf
Merge pull request #1775 from molecula/generate-test-data-FB-971
generate csv files that simulate Samsung's data
2021-11-22 15:22:01 -08:00
kcrodgers24
11f1cd3689 Merge branch 'generate-test-data-FB-971' of github.com:molecula/featurebase into generate-test-data-FB-971 2021-11-22 14:55:14 -08:00
kcrodgers24
50e7cda07f modify functions to accept a requested num of records 2021-11-22 14:53:17 -08:00
Kasey C. Rodgers
cc65263ac5
Merge branch 'master' into generate-test-data-FB-971 2021-11-22 14:22:31 -08:00
kcrodgers24
4c9edabd6d Merge branch 'master' into generate-test-data-FB-971 2021-11-22 14:19:16 -08:00
reese
3789a8dd05
Merge pull request #1780 from molecula/sup-100
[SUP-100] fix bug where timestamp val is wrong in Min/Max
2021-11-22 16:10:55 -06:00
kcrodgers24
49289f2237 replace fmt.Print with t.Fatal, and improve date generator 2021-11-22 13:53:41 -08:00
reesporte
f0434a29d0 Merge branch 'sup-100' of github.com:molecula/featurebase into sup-100 2021-11-22 15:06:07 -06:00
reesporte
88fd6b1a9a remove helper status 2021-11-22 15:06:00 -06:00
reese
868a84f9fb
Merge branch 'master' into sup-100 2021-11-22 14:48:02 -06:00
souhailanoor
221fd4d4e7
Merge pull request #1783 from molecula/delete_EC2_node_on_failure
Fix bug for deleting Ec2 nodes when job fails
2021-11-22 14:34:24 -06:00
Souhaila Noor
c51a2de672 fixed dependency error 2021-11-22 14:10:34 -06:00
Souhaila Noor
f7fc380bcd split aws commands to allow for better error handling 2021-11-22 13:14:58 -06:00
kcrodgers24
06be6c0981 use log.Fatal in lieu of fmt.Print 2021-11-22 11:06:38 -08:00
reesporte
8918d91a09 Merge branch 'master' into sup-100 2021-11-22 13:05:40 -06:00
kcrodgers24
2385fda259 add tests, remove commented code 2021-11-22 10:45:12 -08:00
kcrodgers24
97c4ee670b add tests 2021-11-22 10:43:13 -08:00
Souhaila Noor
a32a217dbd test error condition 2021-11-22 12:10:42 -06:00
Souhaila Noor
55d35365c6 allow failure for ec2 node job 2021-11-22 10:53:42 -06:00
reesporte
fa635874d4 encode/decode timestamp val appropriately 2021-11-22 10:08:18 -06:00
souhailanoor
15877b897e
Merge pull request #1782 from molecula/decreaseTimeForCICD
Decrease sleep time for gitlab CICD pipeline
2021-11-19 15:05:48 -06:00
Souhaila Noor
2cde034e82 testing reviewer's suggestion 2021-11-19 14:40:37 -06:00
reesporte
e4745c1d77 add test for timestamp Min/Max on multinode clusters 2021-11-19 14:32:08 -06:00
souhailanoor
5d7469c519
Merge branch 'master' into decreaseTimeForCICD 2021-11-19 13:47:57 -06:00
kcrodgers24
4f5f27f513 make error handling best 2021-11-19 11:47:32 -08:00
Matthew Jaffee
0614665a29
Merge pull request #1781 from molecula/remove-cloudbuild
remove unused .cloudbuild directory (was for GCP CI stuff)
2021-11-19 13:41:20 -06:00
souhailanoor
99e50c25aa
Merge branch 'master' into decreaseTimeForCICD 2021-11-19 13:19:10 -06:00
Souhaila Noor
c83170f1f0 decrease sleep time 2021-11-19 13:16:48 -06:00
Matthew Jaffee
a02a8a94b3 remove unused .cloudbuild directory (was for GCP CI stuff) 2021-11-19 12:50:40 -06:00
tgruben
aecc6547c0
Merge pull request #1779 from molecula/FB-972-query
[FB-972] Random query and load tester
2021-11-19 12:48:20 -06:00
tgruben
df9ba3d2db
Merge branch 'master' into FB-972-query 2021-11-19 12:33:02 -06:00
Todd Gruben
5c5e16af33 added a generate only flag 2021-11-19 12:26:23 -06:00
Todd Gruben
f4a40e79b9 final cleanup 2021-11-19 12:08:24 -06:00
Matthew Jaffee
f6e9b6ab40
Merge pull request #1762 from molecula/clean-up-top-level
remove outdated files at top level
2021-11-19 11:53:01 -06:00
kcrodgers24
dc9c2a842a make error handling better 2021-11-19 09:38:12 -08:00
Todd Gruben
989f9c3f48 applied suggestions 2021-11-19 11:29:17 -06:00
Matthew Jaffee
25e5c6f5fb remove references to CONTRIBUTING and CHANGELOG 2021-11-19 11:22:15 -06:00
Todd Gruben
b12f00db59 changed default seed to current time 2021-11-19 10:57:36 -06:00
Matthew Jaffee
f7b4f621a1 remove references to LICENSE and checks for it in source files 2021-11-19 10:38:06 -06:00
Todd Gruben
1089435218 add check for index presence 2021-11-19 09:48:45 -06:00
Todd Gruben
c72406819e added seed param 2021-11-19 09:40:39 -06:00
reesporte
ff39b76143 remove extra line smh my head 2021-11-19 09:32:41 -06:00
reesporte
caebbffe6c Merge branch 'sup-100' of github.com:molecula/featurebase into sup-100 2021-11-19 09:24:15 -06:00
reesporte
0adfa75188 add unit test
we can avoid regressions with a simple unit test that checks that timestamp
ValCounts have the appropriate values in comparisons
2021-11-19 09:23:01 -06:00
Matthew Jaffee
b3b11638a3 remove outdated files at top level
we're no longer Apache 2.0 licensed, or open source, so LICENSE and
CONTRIBUTING.MD are gone. We track the changelog elsewhere, so that
can go, and I don't think anyone has looked at the NOTES file in 3
years. I modified the NOTICE not to refer to the Apache license any
more.
2021-11-19 09:03:14 -06:00
Todd Gruben
de7af694fd Merge branch 'FB-972-query' of github.com:molecula/pilosa into FB-972-query 2021-11-19 05:17:22 -06:00
Todd Gruben
f6b3a81ac3 made duration minutes for query rate 2021-11-19 05:16:30 -06:00
kcrodgers24
85629c85b7 Merge branch 'generate-test-data-FB-971' of github.com:molecula/featurebase into generate-test-data-FB-971 2021-11-18 16:16:56 -08:00
kcrodgers24
b5e5df8b58 add error checking 2021-11-18 16:10:49 -08:00
reese
ec1231ff57
Merge branch 'master' into sup-100 2021-11-18 17:30:37 -06:00
reesporte
8f85a9e88d fix bug where timestamp val is wrong in Min/Max 2021-11-18 17:27:13 -06:00
tgruben
cbd7a4f30c
Merge branch 'master' into FB-972-query 2021-11-18 17:17:32 -06:00
Souhaila Noor
ce13bb78ed fixed typo 2021-11-18 17:09:52 -06:00
nagamocha3000
ae95fa2a2a
Merge pull request #1778 from molecula/install
add config files for release
2021-11-19 02:02:25 +03:00
kcrodgers24
27b73d2b7d corrects typo on line 229 2021-11-18 14:27:19 -08:00
nm
3b92f9493d add config files for release 2021-11-19 01:26:18 +03:00
Todd Gruben
87ededd61e Modified random query to use vegeta library 2021-11-18 16:23:12 -06:00
kcrodgers24
90ace6b970 deletes duplicate file and adds license header 2021-11-18 13:47:23 -08:00
kcrodgers24
14050c567c corrects naming convention and age range 2021-11-18 13:15:44 -08:00
souhailanoor
bbbcc7d677
Merge branch 'master' into generate-test-data-FB-971 2021-11-18 14:44:20 -06:00
souhailanoor
6623cbba8d
Merge pull request #1777 from molecula/fixEC2NodeBug
fix for ec2 ip filtering
2021-11-18 13:37:31 -06:00
souhailanoor
d8967dfb96
Merge branch 'master' into fixEC2NodeBug 2021-11-18 13:06:44 -06:00
seebs
8ae19b3c36
Merge pull request #1766 from molecula/fb1019
FB-1019: internal consistency errors in RBF
2021-11-18 12:57:41 -06:00
Souhaila Noor
4e3f31471c remove double quotes from variable name 2021-11-18 12:42:09 -06:00
Souhaila Noor
5d489198bd fixed apt install bug 2021-11-18 12:11:48 -06:00
Souhaila Noor
d40eefb364 added host:port as a command line input 2021-11-18 12:06:07 -06:00
Souhaila Noor
eb717f568d fix for ec2 ip filtering 2021-11-18 11:49:38 -06:00
tgruben
b6875476ff
Merge branch 'master' into generate-test-data-FB-971 2021-11-18 10:30:06 -06:00
Todd Gruben
442d109814 created qa folder 2021-11-18 10:28:49 -06:00
Seebs
9c0c0ec8c1 There are two related bugs here.
First, it is possible for us to end up allocating *or freeing* pages during
a modification of the free list, in a way such that the change to the free list
means that when we finish the modification which caused the allocate or free,
we've overwritten the inner change.

Second, when deallocating trees, we don't actually deallocate the branch nodes
themselves.

The former causes potentially severe data corruption. The latter causes us
to gradually leak pages in a way that we don't notice because we only run those
tests during the RBF tests.

The fix for this is surprisingly intricate, because of the counterintuitive
fact that *allocating* a page means *removing* things from the free list
(and thus potentially deallocating free list pages), while *freeing* a page
means *adding* things to the free list (and thus potentially needing to
allocate pages for the free list).

While modifying the free list, any allocations we need always just come from
the end of the file; we don't try to reuse free pages. If a page becomes
*deallocated* by a free list modification, we don't annotate it in the free
list at the instant that it happens; we stash that information until the
current modification of the free list happens, then iterate through any
such pages.

I am pretty sure there's virtually never more than one, and I don't actually
know that I can create a case wherein we'd end up with the nested case
firing, wherein removing a page from the free list causes us to remove another
page, but I think if the free list got large and cluttered and needed
rebalancing or something it could maybe happen.
2021-11-18 10:05:55 -06:00
Seebs
a38c219cf3 Add test for RBF failures
This test case triggers a failure in RBF, it's a separate patch to
make it easier to see the failure.
2021-11-18 10:05:54 -06:00
reese
db99b83bb2
Merge pull request #1772 from molecula/sup-102
[SUP-102] fix presentation of timestamps in Groupby, Distinct calls from psql client
2021-11-17 13:15:16 -06:00
Kasey C. Rodgers
9302775fd8
generate csv files that simulate Samsung's data 2021-11-17 08:21:57 -08:00
reesporte
ea96c10114 fix typo 2021-11-17 09:10:50 -06:00
reesporte
6419a87797 use util function for formatting timestamp 2021-11-17 09:07:08 -06:00
reesporte
f8e93871c0 refactor safeCopy to pure function and add unit test 2021-11-17 08:51:28 -06:00
reesporte
7390ae072d Merge branch 'master' into sup-102 2021-11-17 08:11:03 -06:00
seebs
2e0b5cb55b
Merge pull request #1774 from molecula/fbholder
unbreak featurebase holder subcommand
2021-11-16 15:18:06 -06:00
reesporte
1cc6a87d20 refactor and add test 2021-11-16 14:53:30 -06:00
Seebs
dcab1a6708 unbreak featurebase holder subcommand
The "just open the holder" subcommand doesn't work the way it used
to, because now that we rely on etcd to open a holder, trying to open
a holder without things set up just coredumps.

Step 1: Fix that.
Step 2: Also add a test that covers it so we don't get bitrotted again.
Step 3: Remove an unrelated stale comment that doesn't deserve its
own commit log, having to do with an option that no longer exists
which is no longer being set right under the comment saying we set it.
2021-11-16 14:23:35 -06:00
tgruben
7ee343c8fa
Merge pull request #1773 from molecula/fix-ci
Added back code coverage
2021-11-16 12:32:03 -06:00
Todd Gruben
4c966dee22 removed filter 2021-11-16 12:08:46 -06:00
reesporte
9e041803fb add license 2021-11-16 09:20:44 -06:00
reesporte
da783d97ef add test for pgWriteDistinctTimestamp 2021-11-16 09:14:15 -06:00
reesporte
24051111b6 Merge branch 'sup-102' of github.com:molecula/featurebase into sup-102 2021-11-15 17:15:51 -06:00
reesporte
9bbd946ac5 update test to ignore FieldOptions field 2021-11-15 17:15:44 -06:00
reesporte
b3b536505d fix presentation of timestamps from a groupby pql call 2021-11-15 17:15:44 -06:00
reesporte
6d6cf7e51f fix presentation of timestamps from a distinct pql call 2021-11-15 17:15:44 -06:00
reesporte
5767b778b9 Merge branch 'sup-102' of github.com:molecula/featurebase into sup-102 2021-11-15 17:13:26 -06:00
reesporte
f5afb7a3ed update test to ignore FieldOptions field 2021-11-15 17:13:19 -06:00
Todd Gruben
6413ed3228 added protection against trailing slash 2021-11-15 17:13:19 -06:00
Souhaila Noor
8770ce245e ingest and delete for samsung workflow 2021-11-15 17:13:19 -06:00
reese
3e9f78d030
Merge pull request #1769 from molecula/fix-build-lattice
[SUP-106] use go1.16.10 for build and test, add test with go1.17.3
2021-11-15 17:12:32 -06:00
reesporte
269526348e update test to ignore FieldOptions field 2021-11-15 17:03:40 -06:00
reese
d7e0a0a4c3
Merge branch 'master' into sup-102 2021-11-15 16:19:26 -06:00
reese
e817dcf0a8
Merge branch 'master' into fix-build-lattice 2021-11-15 16:04:20 -06:00
reesporte
9e570c9e84 fix presentation of timestamps from a groupby pql call 2021-11-15 15:59:51 -06:00
souhailanoor
875692a033
Merge pull request #1771 from molecula/fb973-ingest
FB-973 Create ingest workload for Samsung Simulacra
2021-11-15 15:34:21 -06:00
reesporte
96dfe845d3 fix presentation of timestamps from a distinct pql call 2021-11-15 15:04:27 -06:00
souhailanoor
54e85b8e6e
Merge branch 'master' into fb973-ingest 2021-11-15 14:55:33 -06:00
Souhaila Noor
f0a6ebae8f ingest and delete for samsung workflow 2021-11-15 14:51:57 -06:00
tgruben
5980d3d278
Merge pull request #1770 from molecula/migrate-bug
[FB-1026] added protection against trailing slash
2021-11-15 13:15:19 -06:00
Todd Gruben
7de69df424 added protection against trailing slash 2021-11-15 10:54:13 -06:00
reesporte
ed5525c836 remove long lines i guess 2021-11-15 10:19:51 -06:00
reesporte
0a4e9fe8cf move lattice build dir to right location 2021-11-15 10:16:43 -06:00
reese
dcab3a4bce
Merge branch 'master' into fix-build-lattice 2021-11-14 15:16:11 -06:00
reesporte
d1345ca265 build all with golang:1.16.10 2021-11-14 15:00:28 -06:00
reesporte
541df0fe37 is it because of the go cache? 2021-11-14 14:40:05 -06:00
reesporte
fd1a2d2e78 smh 2021-11-14 14:26:27 -06:00
reesporte
4995888f00 the problem was i was installing it for a different architecture smh 2021-11-14 14:11:56 -06:00
reesporte
de0e8cc0f9 maybe go bin is in a different spot? 2021-11-14 13:52:44 -06:00
reesporte
9ff56e032e pls 2021-11-14 13:37:57 -06:00
reesporte
0d8ecfbcb5 be more explicit? 2021-11-14 13:22:12 -06:00
reesporte
91271795ac f 2021-11-14 13:07:42 -06:00
reesporte
220515bbd4 "update path" 2021-11-14 12:53:33 -06:00
reesporte
948928c06e set gopath explicitly 2021-11-14 12:37:18 -06:00
reesporte
49ce895c4d change path 2021-11-14 12:19:27 -06:00
reesporte
67835f746d please work 2021-11-14 12:17:09 -06:00
reesporte
14e9fb1ff1 statik h 2021-11-14 12:02:45 -06:00
reesporte
a214ac5ded verbose statik install 2021-11-14 11:46:52 -06:00
reesporte
b28c9feef0 more print debug 2021-11-11 18:28:20 -06:00
reesporte
1337a9dfaa more debugging by print statement 2021-11-11 18:12:27 -06:00
reesporte
640d12cb6c debug by print statmeentS 2021-11-11 17:54:26 -06:00
reesporte
61d558de3c update tests, actually install statik smh my head 2021-11-11 17:40:28 -06:00
reesporte
0ab58b9132 untar properly 2021-11-11 17:23:34 -06:00
reesporte
37866204d7 use statik right 2021-11-11 17:09:14 -06:00
reesporte
bd209b3005 please god work 2021-11-11 16:46:10 -06:00
reesporte
58c01793cb this ought to do it 2021-11-11 16:25:51 -06:00
tgruben
5a68470339
Merge pull request #1768 from molecula/upgrad-go
upgrade go builder to 1.16.10
2021-11-11 16:19:15 -06:00
reesporte
d449c8449f don't treat warnings as errors 2021-11-11 16:17:38 -06:00
reesporte
531957c51f hope 2021-11-11 16:05:43 -06:00
tgruben
2f504ff43d
Merge branch 'master' into upgrad-go 2021-11-11 15:47:59 -06:00
Todd Gruben
253ca1182e upgrade go 2021-11-11 15:46:45 -06:00
reese
1dc61daa4c
Merge pull request #1764 from molecula/typo-fix
[NA-000] fix typo
2021-11-11 11:31:32 -06:00
reesporte
02baec2c6e oops 2021-11-11 11:02:51 -06:00
reesporte
9ef057cc85 fix typo 2021-11-11 10:27:31 -06:00
souhailanoor
c62f9715c5
Merge pull request #1750 from molecula/FB-900_singleNodeDeployment
FB-900: aws single node deployment for linux amd64 binary
2021-11-08 16:59:01 -06:00
Souhaila Noor
a8707b55bd updated instance type 2021-11-08 16:14:25 -06:00
Souhaila Noor
05be45194a combined iam role with run-instance 2021-11-08 15:54:12 -06:00
Souhaila Noor
1bda8e439d fixed indentation 2021-11-08 15:26:01 -06:00
Souhaila Noor
2607e2dfb1 Merge branch 'FB-900_singleNodeDeployment' of github.com:molecula/featurebase into FB-900_singleNodeDeployment 2021-11-08 15:22:23 -06:00
souhailanoor
88ba24828c
Merge branch 'master' into FB-900_singleNodeDeployment 2021-11-08 15:16:01 -06:00
Souhaila Noor
d48da50cf6 consolidated some commands 2021-11-08 15:15:26 -06:00
Souhaila Noor
91e93cb975 fixed stage 2021-11-08 14:47:14 -06:00
Souhaila Noor
d5f5340016 fixed syntax error 2021-11-08 14:44:33 -06:00
Souhaila Noor
4c291180b9 added artifact paths 2021-11-08 14:38:35 -06:00
Souhaila Noor
aab7a2e4be fixed stages 2021-11-08 14:33:34 -06:00
Souhaila Noor
1b503a3ddf made the sleep time longer 2021-11-08 14:32:00 -06:00
Souhaila Noor
d92bd37d71 added another sleep 2021-11-08 14:20:04 -06:00
Souhaila Noor
af4b420d66 added region 2021-11-08 13:58:34 -06:00
Souhaila Noor
48295a5491 added abs paths and add sleep time 2021-11-08 13:50:47 -06:00
Souhaila Noor
3d11f9cebf added profile 2021-11-08 13:35:20 -06:00
Souhaila Noor
c2dfc35bdc added iam role 2021-11-08 13:21:07 -06:00
Souhaila Noor
aa4c7aa901 removed targets flag 2021-11-08 12:00:17 -06:00
Souhaila Noor
fe6bea04c2 fix var assignment 2021-11-08 11:55:17 -06:00
Souhaila Noor
32eb7ab097 access array value 2021-11-08 11:45:41 -06:00
Souhaila Noor
49fd477d95 updated var assignment 2021-11-08 11:39:17 -06:00
Souhaila Noor
6d4ae4c345 changed var assignment 2021-11-08 11:34:10 -06:00
Souhaila Noor
2b315c6634 removed instance id file 2021-11-08 11:23:05 -06:00
Souhaila Noor
26d77c51b5 removed variable overwrite 2021-11-08 11:06:55 -06:00
Souhaila Noor
8edfc0c9ff made instanceId a global variable 2021-11-08 11:00:49 -06:00
Souhaila Noor
4a42571dd9 fix for go 2021-11-08 10:45:10 -06:00
Souhaila Noor
22c0815288 fixed syntax error 2021-11-08 10:31:57 -06:00
Souhaila Noor
d3cc4d7f2a added argument to scp 2021-11-08 10:26:59 -06:00
Souhaila Noor
14265090db fixed arguments 2021-11-08 10:20:10 -06:00
Souhaila Noor
38a17e2b94 fixed typo 2021-11-08 09:40:14 -06:00
Souhaila Noor
1cdc8e4959 added aws image 2021-11-08 09:33:34 -06:00
Souhaila Noor
27e39b933f reverted change to aws configure 2021-11-08 09:21:14 -06:00
Souhaila Noor
ebde0142da add stage to configure featurebase 2021-11-08 09:14:47 -06:00
Souhaila Noor
e629e0165d install correct version of go 2021-11-08 08:42:49 -06:00
Souhaila Noor
aae5374248 fixed stages 2021-11-08 08:18:37 -06:00
Souhaila Noor
1befe2ad32 added aws config for terminate job 2021-11-08 08:10:20 -06:00
Souhaila Noor
4c2832ab31 fixed yaml syntax error 2021-11-08 07:59:15 -06:00
Souhaila Noor
79d1a005ce job to terminate ec2 instance 2021-11-08 07:55:42 -06:00
Souhaila Noor
5b5c003b1e private key fix 2021-11-08 07:43:31 -06:00
Souhaila Noor
df99dd7578 fixed typo 2021-11-07 09:31:34 -06:00
Souhaila Noor
76ba07e806 update ssh key filename 2021-11-07 09:29:46 -06:00
Souhaila Noor
46d6ced5b4 updated ssh permissions 2021-11-07 09:24:40 -06:00
Souhaila Noor
f0b2e6beea updated permissions for ssh key 2021-11-07 09:17:02 -06:00
Souhaila Noor
dfc98e3000 updated sleep time 2021-11-07 09:11:52 -06:00
Souhaila Noor
57d4eb45de gitlab path test2 2021-11-07 08:53:01 -06:00
Souhaila Noor
0e564a00e8 path for cloud-init 2021-11-07 08:47:10 -06:00
Souhaila Noor
606b718428 fixed path for cloud-init 2021-11-07 08:42:40 -06:00
Souhaila Noor
78713c6a8c test cloudinit 2021-11-07 08:39:43 -06:00
reesporte
66c7d59707 remove dot imports from catcher.go 2021-11-05 15:39:50 -05:00
Souhaila Noor
103312be8f added cloutinit 2021-11-05 15:04:09 -05:00
Matthew Jaffee
8d47efb666
Merge pull request #1753 from molecula/add-fgprof
add fgprof endpoint by default
2021-11-05 14:42:18 -05:00
Souhaila Noor
6531f90747 fixed syntax error 2021-11-05 14:26:20 -05:00
Souhaila Noor
bf93278ca3 scp binary 2021-11-05 14:24:02 -05:00
Souhaila Noor
179a0e7624 fixed typo for copy path 2021-11-05 14:03:14 -05:00
Matthew Jaffee
fd50c15243 add fgprof endpoint by default
to aid in debugging performance issues
2021-11-05 14:02:58 -05:00
Souhaila Noor
590e5edc57 reverted to last working version 2021-11-05 13:57:37 -05:00
Souhaila Noor
7a5ba0e5d6 Revert "sanity check for scp"
This reverts commit 86407ebcab.
2021-11-05 13:52:26 -05:00
Souhaila Noor
cf365db944 changed ssh config 2021-11-05 13:47:47 -05:00
Souhaila Noor
98e5f6deaf ssh key 2021-11-05 13:45:11 -05:00
Souhaila Noor
4b2322160b sanity 2021-11-05 13:41:13 -05:00
seebs
f02c5c0354
Merge pull request #1748 from molecula/core932
FB-932: rework Import to reduce copying and network traffic
2021-11-05 13:38:12 -05:00
Souhaila Noor
fae8d2d116 ssh add command 2021-11-05 13:32:15 -05:00
Souhaila Noor
642d4fcb86 fixed variable name 2021-11-05 13:27:03 -05:00
Seebs
c7e4bc0fd0 refactoring experiment
I'm not actually sold on this, but I'm not entirely unsold on it. It seems like
it does reduce the amount of duplication a lot, but also it's sort of a mess.

In the process, noticed that it makes more sense to grab the whole cluster
rather than just the nodes for an arbitrary shard for the shard==^0 case,
because then if we have an API (but no Qcx), we can be reasonably confident
that we'll be able to pick the local node for loopback even if we aren't
using the API directly.

Have thought about whether we should create our own Qcx in cases like that
but I really don't like the idea of automatically creating a Qcx.
2021-11-05 13:06:38 -05:00
Seebs
d4b06d077e Import/ImportValue API rework and improvements
Underlying goal: Don't use the http client to send messages back to the
local host. Also, when sending data to other nodes, don't collate it
from an ImportRequest into a completely different format, then immediately
collate that back into an ImportRequest. This does require changing
the logic over in ctl/import to make it create an ImportRequest.

Also, add additional testing to make sure we're actually trying anything
at all with several combinations (such as submitting import requests
which don't match the configuration of index or field), and improve
test coverage for that.

This introduces the ability to tell an http/client InternalClient about
a specific API that it should use for local queries where applicable.
That's not implemented outside of the import stuff, but should probably
be applied eventually to other things that are trying to talk to many
nodes one of which may be the local node. That behavior is contingent
on passing in a Qcx, because it is implicitly tied to an existing
execution context, and it can't assume that it can create a new one,
because that could deadlock.
2021-11-05 13:06:38 -05:00
Seebs
60ac6a929f make address lookup failures okay on MacOS 2021-11-05 13:06:38 -05:00
Seebs
cff8da346f Improvements and benchmarks for ingest field operation sorting
Reusing the field operation sorting for other things caused me
to hit a bug, also made me curious about a performance issue and
whether it was possible to improve it. Answer: Not easy to improve,
anyway.
2021-11-05 13:06:38 -05:00
Souhaila Noor
4f964aeef4 updated ssh config 2021-11-05 12:53:39 -05:00
Souhaila Noor
86407ebcab sanity check for scp 2021-11-05 12:39:11 -05:00
Souhaila Noor
7c02e9c447 added scp 2021-11-05 12:37:15 -05:00
Ben Johnson
f2bc887d6f
Merge pull request #1751 from molecula/fb-904
[FB-904] Add deb/rpm packaging of FeatureBase binary
2021-11-05 10:59:48 -06:00
Souhaila Noor
d080164a49 echo aws config 2021-11-05 11:35:54 -05:00
Souhaila Noor
ab3679bef7 sanity check 2021-11-05 11:33:17 -05:00
Souhaila Noor
6e6d7a77db debug echo statements 2021-11-05 11:26:09 -05:00
tgruben
fd08815f51
Merge branch 'master' into fb-904 2021-11-05 11:23:01 -05:00
Souhaila Noor
a9ab597d28 added profile to start-instance 2021-11-05 11:20:21 -05:00
Souhaila Noor
021af2c5e5 changed ssh key name to match aws 2021-11-05 10:56:10 -05:00
Souhaila Noor
0cfd5f116d echo ssh file 2021-11-05 10:50:59 -05:00
Souhaila Noor
550a610b5b sanity checks 2021-11-05 10:46:54 -05:00
Souhaila Noor
f7497bfe8f pass ssh key to a file 2021-11-05 10:35:15 -05:00
Souhaila Noor
6643e3963e reverted back to variable for ssh 2021-11-05 10:28:36 -05:00
Souhaila Noor
04b64c0f30 add path for ssh keys 2021-11-05 09:54:37 -05:00
Samir Patel
6fa8f0a88e
Merge pull request #1749 from molecula/bug/index-bounds
[FB-965] featurebase import: check for data in requests
2021-11-05 09:49:50 -05:00
Souhaila Noor
bd440f4c23 updated permissions for ssh key 2021-11-05 09:43:19 -05:00
Souhaila Noor
d147c03e22 add ssh config in section with using ssh keys 2021-11-05 09:32:53 -05:00
Souhaila Noor
7271821ebe fixed path for ssh keys 2021-11-05 09:28:25 -05:00
Souhaila Noor
14a9662494 fixed yaml syntax error 2021-11-05 09:24:20 -05:00
Souhaila Noor
f9ff3973d0 fixed argument name 2021-11-05 09:17:19 -05:00
Samir Patel
139f4c9cbb
Merge branch 'master' into bug/index-bounds 2021-11-05 09:16:39 -05:00
Samir Patel
cb6a364890 more qcx defers 2021-11-05 09:12:28 -05:00
Souhaila Noor
383663673b configure ssh 2021-11-05 09:11:27 -05:00
Souhaila Noor
321d273dce fixed typo in instance name 2021-11-05 09:03:51 -05:00
Ben Johnson
94c6c4ee53
Merge branch 'master' into fb-904 2021-11-04 16:58:30 -06:00
Samir Patel
20131a697c add additional tests and defer qcx 2021-11-04 17:07:24 -05:00
Samir Patel
cdaec2e0d2 remove duplicate checks 2021-11-04 16:04:00 -05:00
Samir Patel
67233d5720 move checks to api.go 2021-11-04 15:52:37 -05:00
Souhaila Noor
82b97022ff removed sleep time 2021-11-04 14:57:41 -05:00
souhailanoor
268ea74856
Merge branch 'master' into FB-900_singleNodeDeployment 2021-11-04 14:47:46 -05:00
Souhaila Noor
f80f2fc702 added rsa key 2021-11-04 14:34:19 -05:00
Souhaila Noor
08161a366a undo last commit 2021-11-04 13:42:03 -05:00
Souhaila Noor
20224b1df5 updated aws config 2021-11-04 13:28:48 -05:00
reese
2e9b43dfca
Merge pull request #1752 from molecula/sup-86
[SUP-86] slow webui on large query
2021-11-04 12:54:11 -05:00
Samir Patel
c0e201d638 dedup api_test 2021-11-04 12:19:56 -05:00
reesporte
f70fdfb59e remove inline styling 2021-11-04 12:14:01 -05:00
Souhaila Noor
8274a32127 debug profile 2021-11-04 12:09:20 -05:00
reesporte
4891cd1c9a Merge branch 'sup-86' of github.com:molecula/featurebase into sup-86 2021-11-04 11:55:59 -05:00
reesporte
7b3dee5653 single quotify 2021-11-04 11:55:32 -05:00
Souhaila Noor
7a6e7c2fd5 set profile 2021-11-04 11:53:43 -05:00
Souhaila Noor
01260cfcce update profile 2021-11-04 11:38:58 -05:00
Ben Johnson
395f35fc3d FB-904: Add deb/rpm packaging of FeatureBase binary 2021-11-04 10:32:59 -06:00
Souhaila Noor
502f40593e updated profile 2021-11-04 11:26:05 -05:00
Souhaila Noor
67da6d9ffa debug profile 2021-11-04 11:12:30 -05:00
Souhaila Noor
6e673bafa3 configure profile 2021-11-04 10:58:08 -05:00
Souhaila Noor
c19aa7d6b3 changed profile name 2021-11-04 10:27:13 -05:00
Souhaila Noor
b95d013e14 configure aws profile 2021-11-04 10:12:26 -05:00
Souhaila Noor
50f409771f updated aws profile 2021-11-04 09:59:11 -05:00
Souhaila Noor
df2064a860 define aws credential variables 2021-11-04 09:31:31 -05:00
Souhaila Noor
6ee2341c88 undo last commit changes 2021-11-04 09:04:43 -05:00
Souhaila Noor
e1ca09a7b5 comment other parts of script to speed up testing 2021-11-04 09:02:17 -05:00
Souhaila Noor
c29dcddca6 replace terraform with awscli for integration test 2021-11-04 08:57:10 -05:00
reese
cdbd8b6da7
Merge branch 'master' into sup-86 2021-11-03 13:20:21 -05:00
reesporte
e11ce9a248 clearer wording 2021-11-03 13:18:41 -05:00
reesporte
1585313a0c better styling 2021-11-03 13:14:28 -05:00
reesporte
f9c78091ab move warning label to results count 2021-11-03 13:05:47 -05:00
tgruben
63fd5100d1
Merge pull request #1740 from molecula/golangci-lint
[FB-895] gofmt govet
2021-11-03 10:14:47 -05:00
Todd Gruben
2e086b866a . 2021-11-03 09:37:52 -05:00
Todd Gruben
792032d8b2 Merge branch 'golangci-lint' of github.com:molecula/pilosa into golangci-lint 2021-11-03 09:02:56 -05:00
Todd Gruben
41ed706d83 add license 2021-11-03 09:02:47 -05:00
tgruben
3318b79710
Merge branch 'master' into golangci-lint 2021-11-03 08:58:33 -05:00
Todd Gruben
7fa71d9548 check selecthandler 2021-11-03 08:57:24 -05:00
Todd Gruben
e915d75df6 remove @ from yaml
try to fix yml syntax

same

same

same

same2

same3

same4

same5

try with shell runner instead of dind

remove lattice from dockerfile

change path to bin

runs after linux arm64 build

change dockerfile path

same

same

add dir

better test coverage
2021-11-03 08:48:57 -05:00
reesporte
ad2f5c5ed4 limit the number of results that we keep
also tells the user how many results there were, but they only
get to see 1000 of them
2021-11-02 16:03:43 -05:00
Samir Patel
2bc2640fbf test two scenarios 2021-11-02 15:50:48 -05:00
Samir Patel
3ca91bba7f More specific error message on mismatch 2021-11-02 15:49:59 -05:00
Souhaila Noor
a8d3d1c4d4 fix terraform apply inputs 2021-11-02 15:00:58 -05:00
Souhaila Noor
f3884e21ba changed directory name for terraform files 2021-11-02 14:40:06 -05:00
Souhaila Noor
01e4ae4070 fix missing plan file for terraform apply 2021-11-02 14:13:53 -05:00
Souhaila Noor
d565303160 fix script not running in correct directory 2021-11-02 13:28:33 -05:00
Souhaila Noor
39f85fe2a4 added terraform config for aws single node deployment 2021-11-02 12:25:01 -05:00
Todd Gruben
a79bb893af test ToRows 2021-11-02 12:14:57 -05:00
Todd Gruben
f8d4d83e1a check op log 2021-11-02 10:54:56 -05:00
Samir Patel
4fd2a4fedd
Merge pull request #1737 from molecula/CI/build-containers
[CORE-898] Create FeatureBase Docker Images in CI
2021-11-02 09:41:24 -05:00
reesporte
5d7a399500 go mod tidy! 2021-11-01 19:24:18 -05:00
Samir Patel
5206e8fa0e more comprehensive value check 2021-11-01 18:19:38 -05:00
Samir Patel
1de6085782 remove empty value check from handler 2021-11-01 17:51:16 -05:00
Samir Patel
002b65c516 add checks for data presence on import req 2021-11-01 17:04:33 -05:00
reesporte
25d9895a21 actually get coverage on every single package and subpackage (slow) 2021-11-01 16:49:27 -05:00
reesporte
35d35d9d4d get rid of coverage html since we dont use it 2021-11-01 14:33:57 -05:00
Todd Gruben
2f92fd2a9a all the things 2021-11-01 12:49:27 -05:00
Todd Gruben
ff6a85b728 cvrpkg try again 2021-11-01 12:33:59 -05:00
Todd Gruben
745c34bbfd remove syntload 2021-11-01 12:27:44 -05:00
Todd Gruben
b9b9b0b9cf coverage fun part2 2021-11-01 12:17:17 -05:00
Todd Gruben
76f7690ede Merge branch 'golangci-lint' of github.com:molecula/pilosa into golangci-lint 2021-11-01 11:59:45 -05:00
Todd Gruben
2dab5ac8b2 coverage fun 2021-11-01 11:59:22 -05:00
tgruben
7e0ada9e1a
Merge branch 'master' into golangci-lint 2021-11-01 11:33:56 -05:00
Todd Gruben
9f67866e95 include subpackages in coverage 2021-11-01 11:21:57 -05:00
Samir Patel
a2ba7f39ea Merge branch 'CI/build-containers' of github.com:molecula/featurebase into CI/build-containers 2021-11-01 10:48:36 -05:00
Samir Patel
ab495a3e7b Merge branch 'master' of github.com:molecula/featurebase into CI/build-containers 2021-11-01 10:46:10 -05:00
Samir Patel
a084ad0753 Up goverversion to 1.16.9 2021-11-01 10:44:01 -05:00
reese
e769c085ae
Merge pull request #1746 from molecula/sup-85
[SUP-85] add quotes around strings in webui representation
2021-11-01 10:42:14 -05:00
reese
7d47663b44
Merge branch 'master' into sup-85 2021-11-01 10:31:04 -05:00
Samir Patel
584cac2517
Merge pull request #1743 from molecula/54mir/toggle-schema-details
[FB-920] Add cmd option to disable cardinality calculation in schema/details endpoint
2021-11-01 10:24:24 -05:00
reesporte
510dd4dfb7 un-prettify for less lines of code changed :) 2021-11-01 09:36:36 -05:00
Samir Patel
3fb9395ce0
Merge branch 'master' into CI/build-containers 2021-11-01 09:32:02 -05:00
Samir Patel
8ee0528858
Merge branch 'master' into 54mir/toggle-schema-details 2021-11-01 09:31:35 -05:00
reesporte
705efc1b8a refactor for easier reading, add more tests 2021-11-01 09:25:07 -05:00
Samir Patel
faa831928c Add some error handling 2021-10-31 23:48:43 -05:00
Samir Patel
163492801f Add test to test endpoint code directly 2021-10-31 23:18:53 -05:00
Todd Gruben
f6f8db941d add tes for sonar? 2021-10-30 11:52:46 -05:00
Todd Gruben
521ada8e70 bug with shadow correction 2021-10-30 10:44:23 -05:00
Samir Patel
d828d73eae Add APISetOptions test for coverage 2021-10-29 19:04:21 -05:00
Todd Gruben
bba60eb20d add key to cache 2021-10-29 17:01:45 -05:00
Samir Patel
21969b1637 Add unit test 2021-10-29 16:52:09 -05:00
reesporte
4a18973274 use prettier to format changed files 2021-10-29 16:16:59 -05:00
reesporte
77e8d6cdc9 Merge branch 'sup-85' of github.com:molecula/featurebase into sup-85 2021-10-29 16:06:35 -05:00
reesporte
ad0b6db841 refactor css as import 2021-10-29 16:04:58 -05:00
Todd Gruben
2d33c40a50 maybe without before? 2021-10-29 15:08:09 -05:00
Todd Gruben
7ca714e6d1 added the linter back to circle 2021-10-29 13:50:41 -05:00
Todd Gruben
2ddcbce8ad fix govet and gofmt errors in existing code 2021-10-29 13:14:27 -05:00
Todd Gruben
8af9cfbb7d removed --new check 2021-10-29 13:14:27 -05:00
Todd Gruben
396e1e6433 . 2021-10-29 13:14:27 -05:00
Todd Gruben
21283e123f remove timeout 2021-10-29 13:14:27 -05:00
Todd Gruben
ac3445b8a5 disable lint on circleci 2021-10-29 13:14:27 -05:00
Todd Gruben
6d6cf655c5 clean gofmt 2021-10-29 13:14:27 -05:00
Todd Gruben
36fa27e2a2 limit linters to only specified 2021-10-29 13:14:27 -05:00
Todd Gruben
113c6bc21a cleanup gofmt 2021-10-29 13:14:27 -05:00
Todd Gruben
2b03c97a38 only run latest try2 2021-10-29 13:14:27 -05:00
Todd Gruben
d1baac6239 only check for new issues 2021-10-29 13:14:27 -05:00
Todd Gruben
f4a47346b0 add golangci-lint to gitlab pipeline. Currently gofmt and govet 2021-10-29 13:14:27 -05:00
Todd Gruben
7e14008ed8 add golangci-lint to gitlab container 2021-10-29 13:14:27 -05:00
reese
86e7058c8c
Merge branch 'master' into sup-85 2021-10-29 12:32:56 -05:00
seebs
84f6a5570f
Merge pull request #1747 from molecula/gopsutilupg
uprev gopsutil
2021-10-29 12:14:11 -05:00
reesporte
f04cb01e5d meaningless commit 2021-10-29 11:56:09 -05:00
reesporte
e520277c71 please work holy moly 2021-10-29 11:33:40 -05:00
reesporte
ff43570881 hopefully this works 2021-10-29 10:32:32 -05:00
reesporte
029fad1fb7 hopefully this works to set up test coverage 2021-10-29 09:34:25 -05:00
reesporte
f6de92ecda set up jest test coverage in gitlab ci 2021-10-29 09:17:12 -05:00
reesporte
8bf4d196e6 set up jest test coverage in gitlab ci 2021-10-29 08:31:08 -05:00
reesporte
04642dad0f hopefully sets up jest test coverage in gitlab 2021-10-29 08:17:10 -05:00
reesporte
ae69ad0d4e add artifact path(s) 2021-10-28 16:21:58 -05:00
reesporte
cdbfcef0eb hopefully updates the ci pipeline to run jest
i updated the gitlab ci pipeline so that hopefully it will run jest coverage stuff for sonar
2021-10-28 16:19:03 -05:00
reesporte
5b869c2810 Merge branch 'sup-85' of github.com:molecula/featurebase into sup-85 2021-10-28 15:16:04 -05:00
reesporte
5ef7975475 refactor and add tests 2021-10-28 15:15:43 -05:00
Seebs
360f161303 uprev gopsutil
The old revision emits a warning on MacOS X that looks concerning, and
even though it's actually mostly-harmless, it is an annoyance.

Also run `go mod tidy` which affected go.sum.
2021-10-28 14:08:13 -05:00
reese
327b358bd2
Merge branch 'master' into sup-85 2021-10-28 13:48:20 -05:00
reesporte
aadfc63bf0 add quotes around strings 2021-10-28 13:45:07 -05:00
Matthew Jaffee
06714aa601
Merge pull request #1744 from molecula/SUP-76-stop-fsyncs
don't fsync on RBF Open if WAL is empty
2021-10-28 13:20:41 -05:00
reesporte
b66a0316e6 Merge branch 'upgrade-node' of github.com:molecula/featurebase into upgrade-node 2021-10-28 11:30:42 -05:00
Samir Patel
b787fccf3a Add cmd option to disable cardinality calc 2021-10-28 10:25:26 -05:00
Matthew Jaffee
c3e14cb9ae don't fsync on RBF Open if WAL is empty
This is targeted at reducing startup times, especially on OSX where
the fsync calls seem to be taking an egregiously long time. I got one
index to go from ~1min to open to ~1sec. This looks safe to me, but
will get opinions from RBF experts.
2021-10-28 09:43:32 -05:00
reese
115b1a9c6a
Merge pull request #1742 from molecula/sup-81
remove shards list from error message entirely
2021-10-28 09:42:57 -05:00
reesporte
968ce78c73 remove ShardSlice entirely 2021-10-27 17:05:56 -05:00
reesporte
bc44f9b8d1 remove shards list from error message entirely 2021-10-27 16:45:17 -05:00
Stephanie Yang
10f235dac1 attempt to upgrade node (to v14) and node-sass (to v4.14) 2021-10-27 13:00:40 -05:00
reese
469791a670
Merge pull request #1739 from molecula/sup-81
[SUP-81] wrap shards list in ShardSlice for prettier output in error messages
2021-10-26 16:04:48 -05:00
reesporte
eb8460c291 wrap shards in error message as ShardSlice for pretty output 2021-10-26 15:39:52 -05:00
reesporte
7c885c8130 export ShardSlice 2021-10-26 15:39:06 -05:00
seebs
6cb9ce0315
Merge pull request #1731 from molecula/core930
[FB-930] remove bolt backend, bluegreentx, and a ton of unused API surface
2021-10-26 13:37:16 -05:00
Seebs
ad30a926f4 Giant Commit: drop a bunch of stuff we don't use.
These commits are hard to disentagle, and doing them separately means
re-modifying the same chunks of code several times before removing it,
and similar things.

Basically:
(1) Drop the bolt backend storage.
(2) Drop the blue-green wrapper that compares two backends.
(3) Drop unused or barely-used Tx API components from all the
remaining backends.
(4) Minor related cleanup to simplify things related to these.

The boltdb backend existed only to verify RBF. The blue-green wrapper
was mostly used to verify RBF, but in practice we had to do a lot
of working around that, and it introduced a lot of special cases.

Types removed:

IteratorFinder: Used only to implement the roaring iterator
on top of boltdb, and to complicate the way it worked in roaring.
Reverted the complications. Also unexport NewSliceContainers
which is used only for that outside of roaring's internals.

PortMapper from cluster_internal_test.go: Used only for a test
we removed early this year. Never used for anything else.

RawRoaringData: Totally unused.

TxStore: Totally unused.

Functions removed from Tx API, and sometimes corresponding
members were removed from structs:

* Dump: debugging code, I don't think I found any actually reachable
  paths to it.
* Group: only used for debugging TxGroup stuff
* IncrementOpN: only used by fragment, fragment can increment its
  own opN.
* Options: unused?
* Pointer: debugging only
* Readonly: used only to decide how to handle Tx in a TxGrp,
  but we never add a non-readonly Tx to a TxGrp. Removed also all
  the corresponding write-aware stuff.
* RoaringBitmapReader: Used exactly once, can just be a bm.WriteTo.
* Sn (and OpenSnList): Unused
* UnionInPlace: unused and conceptually-invalid; it didn't write
  to storage and shouldn't have, and was just "create a bitmap
  then call union-in-place", which we can do directly.
* UseRowCache: just checked storage.UseRowCache.

Other things removed:

The SetRequiredForAtomicWriteTx and ClearRequiredForAtomicWriteTx
functions go away, since nothing now seems to be using them? Same
for holder_internal_test's `testHasBit` and `testMustNotHaveBit`,
which were unused.

The DBPerShard "DeleteDBPath" and "HasData" functions and related
parts were mostly unused; took out the parts that were never
actually being reached.

Changed the API of one function to simplify special cases and
remove things:
* ImportRoaringBits had a special "data" argument which gave it
  subtly different semantics for RBF and roaring (for roaring, it
  could produce a roaring bitmap *with ops log*), didn't seem to
  be adding much. Removed corresponding "readStorageFromArchive"
  which is not otherwise used.

Also took out various debugging/dumping functions that were unused
and may have bitrotted.

Dropped a test from txfactory_internal_test, and the "pjobs"
code, because those two were the only things that needed Barrier
and thus idem, which lets us drop two more dependencies. We already
have errgroup for grouping things which want to terminate as
soon as one of them errors, approximately. To do better we'd have
to have context-threading, really.

Unbroke the WriteFragment test for non-roaring tests and made it
not roaring-only.
2021-10-26 12:30:25 -05:00
Seebs
ecd0ecc6d1 add featurebase to .gitignore
we ignored pilosa binaries but we've renamed so now the binary is named
featurebase.
2021-10-26 09:15:44 -05:00
Seebs
dc8702ea3e use testhook auditor to track Qcx open/close
This also requires doing something to keep the TxGroup in each Qcx
from holding its Tx references after the Qcx closes, because otherwise
the list of Qcxs that we keep to verify that they all got closed ends
up keeping every shared/read-only Tx open forever, resulting in many
gigabytes of memory usage when running with the race detector.  To
avoid having to reason about whether anything would ever access a nil
TxGroup, or run through iteratively zeroing maps, we just make a new
empty group at that point.
2021-10-26 09:13:53 -05:00
reese
53b7d9e210
Merge pull request #1736 from molecula/time-estimate-rules
SUP-75: Change time estimation to use avg time per message
2021-10-25 15:42:09 -05:00
reesporte
d51c6b950f meaningless commit to kick off sonarcloud with new rules 2021-10-25 15:24:55 -05:00
reesporte
d934d117da add test case names 2021-10-22 14:52:57 -05:00
reesporte
5dd4b0e048 rename vars to more sensible names 2021-10-22 14:49:05 -05:00
reesporte
bd0d68b2fd rename function, return pctDone 2021-10-22 12:54:46 -05:00
reesporte
681ed9923d add license header 2021-10-22 11:29:09 -05:00
reesporte
0f108a612d refactor and add unit tests 2021-10-22 11:25:03 -05:00
reesporte
45e36600f3 don't include .*.swp 2021-10-22 10:49:07 -05:00
Samir Patel
c9d25909be cleanup 2021-10-21 16:27:43 -05:00
Samir Patel
3a83537b5e Merge branch 'CI/build-containers' of github.com:molecula/featurebase into CI/build-containers 2021-10-21 16:27:12 -05:00
Samir Patel
44148ed79d Build featurebase docker image in CI.
Add to registry.
2021-10-21 16:20:07 -05:00
reesporte
7102de9f60 off by one error fixed 2021-10-21 16:19:57 -05:00
Samir Patel
64fd686ec4 tag with slug and sha 2021-10-21 15:46:02 -05:00
Samir Patel
b1ee2c7a59 same 2021-10-21 15:25:52 -05:00
Samir Patel
3cf8f9db5e change tag 2021-10-21 15:18:13 -05:00
reesporte
27515a3f98 number of sent messages is just i silly 2021-10-21 14:24:27 -05:00
Samir Patel
e1945bcf1c change commit name to commit slug 2021-10-21 14:20:51 -05:00
Samir Patel
fba75f1a0c same 2021-10-21 14:16:08 -05:00
Samir Patel
2517e11afd try without mv 2021-10-21 14:09:29 -05:00
Samir Patel
c1746fae5b add login 2021-10-21 13:33:21 -05:00
reesporte
adf3e528f5 Change time estimation to use avg time per message
In [SUP-75](https://molecula.atlassian.net/browse/SUP-75?atlOrigin=eyJpIjoiYmU5MzdkMmUyZTAyNGQ2Y2IzMDMzYTgzMDU2Y2ZhNmMiLCJwIjoiaiJ9) Allen
pointed out that the time estimation is really good for the first couple lines of output, but gets exponentially worse as execution continues.

After looking into it, it looks like we’re currently using a heuristic based on the amount of messages processed in the previous
second(ish) which is what results in that sort of exponential drop off.

To remedy this, I adjusted the time estimation calculation to use the average time per message up to the point of calculating the new
estimate to ideally improve estimates over time, with the trade-off of a potentially less accurate estimate to begin with.
2021-10-21 13:09:24 -05:00
Samir Patel
9669745de6 change tag 2021-10-21 12:04:31 -05:00
Samir Patel
466c5a5627 same 2021-10-21 12:00:47 -05:00
Samir Patel
841e79f343 same 2021-10-21 11:51:26 -05:00
Samir Patel
7e1b629504 change docker push url 2021-10-21 11:33:34 -05:00
Samir Patel
30fb649126 make directory changes 2021-10-21 11:18:42 -05:00
Samir Patel
3aec5fd9de print more stuff 2021-10-21 09:38:42 -05:00
Samir Patel
5f152af53a print stuff 2021-10-21 09:17:29 -05:00
Samir Patel
7cde102944 move binary to gitlab 2021-10-21 08:48:02 -05:00
Samir Patel
4ec0f7428a change dir 2021-10-20 19:10:25 -05:00
Samir Patel
adcbc4c801 add -f flag 2021-10-20 18:06:30 -05:00
Samir Patel
2839ef53c9 add dir 2021-10-20 17:30:13 -05:00
Samir Patel
3fcdc6ff9e same 2021-10-20 17:11:03 -05:00
Samir Patel
7b39ab2bbd same 2021-10-20 17:09:34 -05:00
Samir Patel
00b6c2ff8a change dockerfile path 2021-10-20 16:59:03 -05:00
Samir Patel
dd56bdf645 runs after linux arm64 build 2021-10-20 16:50:35 -05:00
Samir Patel
34a04d276e change path to bin 2021-10-20 16:38:07 -05:00
Samir Patel
686f3a8684 remove lattice from dockerfile 2021-10-20 16:23:20 -05:00
Samir Patel
225b4a7a58 try with shell runner instead of dind 2021-10-20 15:17:23 -05:00
Samir Patel
554d3f1e35 same5 2021-10-20 14:34:24 -05:00
Samir Patel
5b0244e228 same4 2021-10-20 14:15:07 -05:00
Samir Patel
bde29ec792 same3 2021-10-20 14:01:05 -05:00
Samir Patel
35dc4aa07a same2 2021-10-20 13:47:29 -05:00
Samir Patel
93a5cab3fc same 2021-10-20 13:05:14 -05:00
Samir Patel
86c45fba1c same 2021-10-20 12:49:49 -05:00
Samir Patel
9e2992424d same 2021-10-20 12:41:38 -05:00
Samir Patel
e2f3a645c1 try to fix yml syntax 2021-10-20 12:28:26 -05:00
Samir Patel
aa0d5040e5 remove @ from yaml 2021-10-20 12:21:05 -05:00
Samir Patel
a83b7f64a0 tests if docker gets built in gitlab 2021-10-20 11:20:20 -05:00
Fletcher Haynes
3605449b53
Merge pull request #1734 from molecula/gitlab
Migrated Cloud Build to GitLab
2021-10-15 10:07:31 -07:00
Fletcher Haynes
72a2689e4c Migrated Cloud Build to GitLab
This adds in a config YAML file for gitlab
2021-10-14 18:37:06 -07:00
nagamocha3000
263a5b86c9
Merge pull request #1733 from nagamocha3000/core-919-field-deadlock
CORE-919 Fix deadlock on field recreation after node restart
2021-10-14 18:20:25 +03:00
nagamocha3000
c6b7089332 Add comment as to why we are using os.Exit instead of panic 2021-10-14 18:07:02 +03:00
nagamocha3000
bce008df26 Fix deadlock on delete then recreate field after node restart 2021-10-14 17:04:09 +03:00
nagamocha3000
07a340ba9d Add test for deadlock on field recreation 2021-10-13 23:11:56 +03:00
tgruben
9d2d30feb7
Merge pull request #1718 from tgruben/sql2-type
Better type support in result set for looker (postgres) sql2 interface
2021-10-12 12:36:15 -05:00
Todd Gruben
4d4f64a339 address ben's comments 2021-10-12 11:21:14 -05:00
Todd Gruben
5d57d361f4 quite down 2021-10-12 10:50:03 -05:00
Todd Gruben
e4e0d13837 go mod tidy correction? 2021-10-12 10:40:32 -05:00
Todd Gruben
c4c7d91bf0 make linker happy 2021-10-12 10:24:19 -05:00
Todd Gruben
34dad863e2 wip 2021-10-12 10:20:24 -05:00
Todd Gruben
caee5680c3 wip 2021-10-12 10:20:24 -05:00
Todd Gruben
1a068cf0e2 added type support for looker; added intercept for yellowfin typelen query 2021-10-12 10:20:24 -05:00
Kasey C. Rodgers
c4a348724e
Merge pull request #1726 from molecula/csv-error-17
adds more detail to CSV ingest error message
2021-10-12 07:04:22 -07:00
Kasey C. Rodgers
25230693c5
Merge branch 'master' into csv-error-17 2021-10-08 13:55:58 -07:00
Kasey C. Rodgers
ded60af8c3
Update pilosa.go
Co-authored-by: Matthew Jaffee <jaffee@pilosa.com>
2021-10-08 13:46:17 -07:00
Fletcher Haynes
276dab6d12
Merge pull request #1728 from molecula/cicd
Added in various CI files
2021-10-08 12:39:08 -07:00
Fletcher Haynes
6eefd2d1f0
Merge branch 'master' into cicd 2021-10-08 12:18:26 -07:00
Fletcher Haynes
155855d97f Added in various CI files
This adds in configs for Cloud Build, Artifactory, and GitLab CI/CD.
2021-10-08 12:16:03 -07:00
tgruben
746212f63f
Merge pull request #1727 from tgruben/wip-partial-restore
partial backup/restore
2021-10-08 12:58:33 -05:00
Todd Gruben
71f1e6f1dd linter 2021-10-08 12:20:53 -05:00
kcrodgers24
b2c73b6a41 changes error message text for additional clarity 2021-10-08 09:47:16 -07:00
Todd Gruben
786bebe58b partial backup/restore 2021-10-08 10:50:52 -05:00
kcrodgers24
1f257aab9c adds more detail to CSV ingest error message 2021-10-08 08:27:49 -07:00
Ben Johnson
0d548094eb
Merge pull request #1724 from molecula/sql-inner-join
CORE-809: Aggregate COUNT() with INNER JOIN
2021-10-07 14:56:28 -06:00
Ben Johnson
98e7ade591 CORE-809: Aggregate COUNT() with INNER JOIN 2021-10-07 14:20:07 -06:00
seebs
39aa12b12a
Merge pull request #1723 from molecula/seebs/genfix
don't close storage after failing to open cache
2021-10-01 15:52:42 -05:00
Seebs
8433f81b68 don't close storage after failing to open cache
If the inner function that handles the open of storage and cache
fails, we close the fragment. If we closeStorage() before that,
then we can try to close the storage again, which causes a panic
when we try to mark the generation as Done again.

I was going to set f.gen = nil after marking it done, but I'm
not feeling safe about that -- there's too many places where
we check things about f.gen, and it seems unsafe. The generation
code should be removed at some point, because it all exists
as a workaround for not having any way to detect when reads are
"done", because we didn't want to do something huge and intrusive,
like adding the Tx system and requiring transactions to get
closed.
2021-10-01 11:02:45 -05:00
seebs
8ed922d30e
Merge pull request #1720 from molecula/fsync
Fsync
2021-10-01 10:58:13 -05:00
Seebs
9db87f78d0 fix go.mod/go.sum 2021-10-01 10:45:08 -05:00
Seebs
214a1492a8 kill off a ton more fsyncs
Performance of tests on MacOS has been atrocious for a while, and
a lot of that is fsync, so we're trying to make that optional.

To test all of this, I modified RBF to panic if anything tried to
open an RBF database without disabling fsync, and ran the tests that
way, and tracked down the various places this could still happen.

There's a lot of places in our tree where we were creating
test holders which were not getting created with fsync disabled, which
results in a surprisingly large number of points at which we end
up calling fsync in tests, which makes tests much slower than they
need to be. There's also a bunch of places where the flags don't get
propagated correctly; for instance, storage.fsync didn't propagate
to the RBFConfig.

We add an "fsync enabled" flag to OpenTranslateStoreFunc, so we can
tell translation stores that we don't need syncing, so the server's
config can be passed on appropriately.

More of the test code that sets things up is correctly configuring
that flag by default.

We also change the barely-used bolt storage backend to support this as
well.

With this done, the only calls to fsync left in a run of `go test -short`
in the top-level directory are from the zap logger in etcd, and consumed
around 0.03 seconds. The overall impact is that `go test -short`
went from "takes enough more than 10 minutes that i don't know how long
it takes" to about 2.5 minutes.
2021-10-01 10:45:08 -05:00
Seebs
e774acb4a0 disable a few more fsyncs in boltdb
boltdb has a couple of places where it fsyncs even when fsync is
disabled, this turns out to cost an amazing amount of time over
several thousand databases in our test run. In theory, they are
rare circumstances compared to updates; in practice, when you
open 256 partition key translation databases per server opened
and most of them never get written to, not so much.
2021-10-01 10:45:08 -05:00
Seebs
9ac4a5a8f4 don't necessarily fsync RBF databases even on close when fsync is disabled
In test runs, we open, and close, *huge* numbers of databases. Even
the single fsync on close for these ends up being expensive on some
hosts. *cough* Apple. At least in theory, writes delivered to the
disk are just as written whether or not you've hit fsync, as long
as the machine doesn't power off before getting to them. In the
circumstances where we disable fsync, that's fine.

Since we already have an fsync function for "fsync if it's
not disabled", use that.
2021-10-01 10:45:08 -05:00
Seebs
d5b61ee8e8 reduce etcd fsyncs during testing
We disable fsync more consistently in testing, including using
etcd's already-existing UnsafeNoFsync option to disable fsyncs
in the backing store boltdb used by etcd, to reduce runtime of
our tests on MacOS significantly.

Corresponding to this, we update etcd by one patch to pick
up a locally-invented patch which turns out to be nearly-identical
to the upstream fix for "disabling fsync makes boltdb not
even bother to write some data sometimes", which caused crashes
galore.
2021-10-01 10:45:08 -05:00
Samir Patel
231e11ffe8
Merge pull request #1719 from 54mir/54mir/log-roaring-migrate
CORE-874 Add darwin build to roaring-migrate-tool
2021-10-01 10:35:22 -05:00
tgruben
c750717f50
Merge branch 'master' into 54mir/log-roaring-migrate 2021-10-01 10:02:46 -05:00
nagamocha3000
7a597610e2
Merge pull request #1710 from nagamocha3000/core-849-prevent-node-from-blocking-replication-process
CORE-849 Test paused node picks up once cluster state is back to normal
2021-09-30 21:07:48 +03:00
nagamocha3000
c24a5e77ba Test paused node picks up once cluster state is back to normal
This adds the following test:
1. cluster comes up (node 1,2,3), status normal
2. Pause node 3
3. Insert keys making sure to filter out the keys that will go to the paused node
4. Wait for status to become degraded
5. Unpause node 3
6. Wait for status to get back to normal
7. Check that keys were replicated to all 3 nodes
2021-09-30 20:48:01 +03:00
seebs
4648aa9477
Merge pull request #1713 from molecula/seebs/core829
rework executor's per-shard union to use UnionInPlace
2021-09-30 11:26:31 -05:00
Samir Patel
a845d93a25 Add license headers 2021-09-30 09:28:33 -05:00
Samir Patel
5d070b47bb clean up 2021-09-29 15:57:31 -05:00
Samir Patel
feb8997ca8 Add darwin build to roaring-migrate-tool 2021-09-29 15:42:50 -05:00
Seebs
3ef25e4a16 rework executor's per-shard union to use UnionInPlace
The actual code here is mostly jaffee's, but I've reworked it some.

This doesn't directly seem to be using UnionInPlace, but really it
is.

The actual logic inside (*Row).Union is a mess and probably silly
in a few ways, but hardly matters. The important part is that,
instead of calling it once per child as we get them, we gather
all of them at once and then call it on all of them. That gets
us a call to (*Row).Union that does a very elaborate dance to
compute a call to (*rowSegment).Union on the only segment present
in each of those rows, which then does a simpler thing to
call (*Bitmap).Union() with the first response as a receiver
and the rest as parameters, and THAT then ends up calling either
unionIntoTargetSingle() if there's only one other bitmap,
or using UnionInPlace on a Freeze() of the first bitmap, which
gets us (we hope) the benefits of the fancy UnionInPlace logic.

Every part of this is a reminder that we really need to replace
roaring and also the Row/rowSegment stuff some day.
2021-09-29 11:31:13 -05:00
souhailanoor
e5479390b8
Merge pull request #1717 from molecula/CORE-844_webUI_rename
CORE-844: remove Pilosa name and website from curl handler for webUI endpoints
2021-09-28 17:23:51 -05:00
souhailanoor
68d1126ac9
Merge branch 'master' into CORE-844_webUI_rename 2021-09-28 17:12:16 -05:00
Souhaila Noor
49e8c1c69f undid the changes pushed earlier for incrementing the release version 2021-09-28 16:59:54 -05:00
Souhaila Noor
3fe28ca7b9 renamed webUI from Pilosa to FeatureBase and updated version 2021-09-28 16:34:52 -05:00
Ben Johnson
938c425d80
Merge pull request #1716 from molecula/sql-scan
CORE-860: Allow StmtRows.Scan() for more types
2021-09-28 15:06:35 -06:00
tgruben
7cf5e5c804
Merge branch 'master' into sql-scan 2021-09-28 15:52:41 -05:00
Ben Johnson
b7126a5859 Allow StmtRows.Scan() for more types 2021-09-28 13:16:24 -06:00
tgruben
f0b93da070
Merge pull request #1715 from tgruben/cleanup-query
addsql version to handler
2021-09-27 16:37:04 -05:00
tgruben
8861e4528a
Merge branch 'master' into cleanup-query 2021-09-27 16:24:06 -05:00
seebs
8fd6ebc8da
Merge pull request #1711 from molecula/seebs/clusterIngest
CORE-826: cluster support for ingest API
2021-09-27 16:22:37 -05:00
Todd Gruben
79c066a9a0 mod tidy fun 2021-09-27 16:11:27 -05:00
Todd Gruben
2b36625081 missed test handler 2021-09-27 16:04:40 -05:00
Todd Gruben
51876b1821 addsql version to handler 2021-09-27 15:42:14 -05:00
Seebs
02d3d24bc5 code review cleanup 2021-09-27 12:05:57 -05:00
Seebs
12882ad147 handle replication
I assumed the existing import code handled replicas. It doesn't, actually.
It just assumes they're handled. So, in the new import code, when splitting
things up by-shard, send each shard's data to *every* node that has
that shard, not just the first one.
2021-09-27 12:05:57 -05:00
Seebs
b3f82ac894 return early on error instead of writing success status also 2021-09-27 12:05:57 -05:00
Seebs
b41f3554da move stableTranslator into test code
It was useful having this in the package to verify code coverage of
the translator, but that having been verified, I'd sort of rather have
it NOT live in the package at all, it's really a testing-only kind
of thing.
2021-09-27 12:05:57 -05:00
Seebs
4bab752fa7 improve comments 2021-09-27 12:05:57 -05:00
Seebs
b78ce29a3e unexport ShardedRequest.Merge
This function absolutely shouldn't be used outside of testing, so I've
made the tests using it internal tests and unexported the method.
2021-09-27 12:05:57 -05:00
Seebs
610c4ed6cb introduce protobuf types for ingest ops
We add a new protobuf type. Also, protoc changed slightly and remade
some tests, in a way which should have no effects but makes the code
*very* slightly cleaner.

This introduces the first testing code in encoding/proto (whoops)
so that scaffolding is a first draft; if you're looking at this code
and the design is a problem go ahead and fix it.

The purpose of this is to verify that we're actually covering all
the branches in the ingest.ShardedRequest and pb.ShardedIngestRequest
message conversions. (Except the top-level one for a nil request,
which isn't checked by this.)

The coverage report doesn't actually include coverage for the ingest
code, though, so we haven't actually properly tested Compare.
Baby steps!
2021-09-27 12:05:57 -05:00
Seebs
9f271467fb ingest cluster support
We add endpoints and protobuf encode/decode to allow for sending
sharded requests over the wire in protobuf, so we can take our
sharded data and send it to other nodes if needed.

This is a squash of >15 other commits, so a bit of history
is relevant:

The Request type had FieldTypes in it because the field type
information was needed for sharding because sorting requires
that information. We change this around to make the external
sharding operation require the field types, and curry that
through the codec -- the codec is needed to tell the request
how it shards. (This is because the correct sorting order
varies by field type.) Requests (and ShardedRequests) no
longer have that table in them.

And then we hit a nasty bug in production and RCA showed
that our testing wasn't good enough and we need to be more
careful, and I discovered that test coverage in this package
was around 70%.

So, the other big thing here is coverage testing; in order to
make coverage testing viable and programmatically testable,
we have added the ability to render requests *back* to
JSON. This is not a great idea, but it does allow us to do
a lot of sanity-checking and verify that the encodings we're
using are consistent and correct.

This, plus some specific tests of decoding specific flawed
inputs, has caught a number of issues. Which are now fixed!

A lot of internal API surface got slightly changed, in ways
that make it simpler to work with. For instance, the
(*FieldOperation).TranslateUnsigned function doesn't really
need to exist; we can just have a non-method translate
function for unsigned and for signed, and use them based on
field type.

The stable translation hack used for testing had a bug that
could allow it to end up producing incorrect results if you
asked it to translate an ID first rather than exclusively
asking it to translate strings first, this has been
corrected. (This is a bug fix in code that was added
partway through creating this, but is tricky enough to
mention its own comment.)

Test coverage is now just over 90%, and a lot of what's left
is error-check returns that may well be actually unreachable
unless, say, the documentation for encoding/json is full of
lies. Which it probably is.
2021-09-27 12:05:57 -05:00
tgruben
214ae4dfac
Merge pull request #1696 from tgruben/looker-count
[CORE-838] Looker Integration
2021-09-27 09:48:31 -05:00
Todd Gruben
c2caa63978 tidy 2021-09-27 08:20:03 -05:00
Todd Gruben
ed1cf7ffef cleanup and applied review suggestions 2021-09-27 07:05:08 -05:00
Todd Gruben
0920c4c029 silence and rebase 2021-09-25 14:06:55 -05:00
Todd Gruben
c4e64528e0 fix 2021-09-25 13:56:36 -05:00
Todd Gruben
2053319db0 silence reporting 2021-09-25 13:53:19 -05:00
Todd Gruben
3baf15226e make lookPQL a package var 2021-09-25 13:53:19 -05:00
Todd Gruben
fc339b9a62 skipp looker comments on PQL 2021-09-25 13:53:19 -05:00
Todd Gruben
5bc1364cdb wip 2021-09-25 13:53:19 -05:00
Todd Gruben
d6dd1e025b removed extra command complete message
cleanup
2021-09-25 13:53:19 -05:00
Todd Gruben
5176b7ff03 added sqlversion config option 2021-09-25 13:53:19 -05:00
Todd Gruben
2ca7b107d2 removed client1 from clustertests 2021-09-25 13:53:19 -05:00
Todd Gruben
9c8538ec5a docker fix not really related to anything 2021-09-25 13:53:19 -05:00
Todd Gruben
c56fd33924 wip 2021-09-25 13:51:02 -05:00
Todd Gruben
419d1ed05d linter cleanup 2021-09-25 13:51:02 -05:00
Todd Gruben
95dc4a1a50 basic looker connection tests pass
sql1 pass through works
2021-09-25 13:51:02 -05:00
Ben Johnson
ab8c42bfd9
Merge pull request #1714 from molecula/sql-col-mapping
CORE-860: Fix SQL column mappings
2021-09-25 11:23:40 -06:00
Ben Johnson
1527eea14b Fix SQL column mappings 2021-09-25 09:36:11 -06:00
Ben Johnson
9f50689509
Merge pull request #1712 from molecula/sql-type-check
Add SQL type checker
2021-09-24 17:07:52 -06:00
Ben Johnson
ff8f0cab96 Add SQL type checking 2021-09-24 14:02:20 -06:00
Samir Patel
ab5e7d4195
Merge pull request #1709 from 54mir/54mir/rename-pilosa-docker2
CORE-859 CORE-839 Rename docker builds to featurebase (with docker fix)
2021-09-23 10:46:50 -05:00
Samir Patel
3403f2f621 Merge branch '54mir/rename-pilosa-docker2' of github.com:54mir/pilosa into 54mir/rename-pilosa-docker2 2021-09-23 10:17:31 -05:00
Samir Patel
5324431ab0 Rename pilosa to featurebase 2021-09-23 10:16:14 -05:00
tgruben
db5143b7af
Merge branch 'master' into 54mir/rename-pilosa-docker2 2021-09-23 10:03:53 -05:00
Matthew Jaffee
930ec3a403
Merge pull request #1672 from jaffee/better-mmap-error
better explanation for 'cannot allocate memory' error
2021-09-23 09:10:09 -05:00
Matthew Jaffee
693606fa80 better explanation for 'cannot allocate memory' error 2021-09-23 08:32:12 -05:00
Samir Patel
839dd1cd43 Remove prints 2021-09-22 16:02:02 -05:00
Samir Patel
4699c840bc More rename to work with backup and cluster tests 2021-09-22 15:41:17 -05:00
Samir Patel
746ffd4bd1 Rename in docker-tag-push 2021-09-22 15:41:09 -05:00
Samir Patel
0ec855766c Rename in make docker-image 2021-09-22 15:41:05 -05:00
Samir Patel
3ca15cc3c4 Rename docker builds to featurebase 2021-09-22 15:41:00 -05:00
Samir Patel
44897d9310 docker fix 2021-09-22 15:35:52 -05:00
Ben Johnson
14fdfe478b
Merge pull request #1708 from molecula/sql-comment
CORE-860: Handle SQL comments during scan
2021-09-21 08:58:23 -06:00
Ben Johnson
ac022ce0ab CORE-860: Handle SQL comments during scan 2021-09-21 08:29:30 -06:00
Ben Johnson
521e4cadb1
Merge pull request #1707 from molecula/sql-group-by
CORE-830: Implement SQL GROUP BY
2021-09-20 08:28:27 -06:00
Ben Johnson
b4cbd45b84 Implement SQL GROUP BY 2021-09-19 08:45:35 -06:00
Matthew Jaffee
0452237b24
Merge pull request #1702 from seebs/bitmapRun
callback logic fixes for intersectionCallback and containerCallback
2021-09-16 16:06:08 -05:00
Matthew Jaffee
3e222d8771 tweak to locking which should avoid stall/deadlock w/ mutex check
The view.go change is straightforward and fairly obviously more
correct.

The field.go change avoids holding the field read lock for the
duration of the mutex check request. The thinking was that while the
read lock was held something else was attempting to get a write lock,
which blocked all other read locks and something was getting into a
loop. Seebs might have a more detailed explanation, but that's as far
as my understanding goes at the moment. I believe this change is safe
though as we don't read/modify any field level data structures after
grabbing the standard view.
2021-09-16 14:07:31 -05:00
Seebs
e7e3331fb4 test intersectionCallback more carefully
This takes our reasonably broad selection of predefined container
types and tries intersectionCallback on each pair of them, comparing
results against the results of plain old intersect(). We've had
several intersectionCallback fixes recently; every one of them
produces test failures here if reverted or broken, so I have at
least some confidence in this coverage.

Similarly, test everything on containerCallback, verifying that
we get the same set of values called back that we get from Slice().

Both of these were verified with -coverprofile to actually be
hitting all the lines of code that aren't insane edge case
checks like "what if a run is in the wrong order".
2021-09-16 14:05:35 -05:00
Seebs
12244dcbed record stats for intersectionCallback under the right name 2021-09-16 14:05:35 -05:00
Seebs
e0dfde9934 appease gofmt 2021-09-16 14:05:35 -05:00
Seebs
3ae12391c7 callback logic fixes for intersectionCallback and containerCallback
The inner loop of intersectionCallbackArrayArray's "fast"
case has
	for len(ca) > 0 && ca[0] < va {
	}
so we do not leave that loop unless len(ca) is 0, or
ca[0] >= va.

We then return from the whole function if len(ca) is 0,
so the only way we finish one iteration of the outer for
loop is if ca[0] >= va. Thus, this can be an `if` rather
than a `for`.

We also fix the logic for ArrayRun to make it require fewer
tests and be clearer about why the tests work and clearer about
always making progress.

And, finally, the bitmap/range callback logic, and the underlying
"callback per bit in word" logic, were both badly broken. In
particular, if a range started and ended in the same word, it would
hit the values in that word twice, once with them incorrectly
shifted, but then it would further garble any offsets past the first
in a word. Eww.
2021-09-16 14:05:35 -05:00
rachithrr
cd1e17d0ba
Merge pull request #1695 from rachithrr/decimal-groupby-added
CORE-777: Added DecimalAgg field in GroupCount to output decimal sum
2021-09-16 10:49:57 -05:00
rachithrr
9e84647e63
Merge branch 'master' into decimal-groupby-added 2021-09-16 09:49:31 -05:00
rachithrr
f549dae625 CORE-777: Added DecimalAgg field in GroupCount to output decimal sum
-created groupCountDecimal
-added test
2021-09-16 09:43:13 -05:00
Kasey C. Rodgers
61c6ffced8
Merge pull request #1690 from molecula/supportARM64-799
add support for ARM64 [CORE-799]
2021-09-14 08:07:09 -07:00
Kasey C. Rodgers
2ae1de8ad6 Update Makefile
corrected typo in docker-release section
2021-09-14 07:31:23 -07:00
kcrodgers24
efcb0768db wip 2021-09-14 07:31:23 -07:00
kcrodgers24
ba10b3dfde add support for ARM64 2021-09-14 07:31:23 -07:00
seebs
1b3e441645
Merge pull request #1697 from seebs/mutexFix
add clusters to MutexCheck test, fix silly bug revealed by doing so
2021-09-14 09:07:56 -05:00
tgruben
66871c70a8
Merge branch 'master' into mutexFix 2021-09-14 08:27:02 -05:00
nagamocha3000
248ec8ebff
Merge pull request #1677 from nagamocha3000/ha_key_translation
CORE-837 Perform partial replication for index keys
2021-09-14 10:53:44 +03:00
nagamocha3000
575854df8a Make index-key replication more resilient to network failures 2021-09-14 03:12:52 +03:00
Seebs
72444f3b87 add clusters to MutexCheck test, fix silly bug revealed by doing so
The merge lists behavior was flawed in that it would drop one item
from the list per merge, which means that, with high replication
and low number of distinct items, it could even produce an empty
list.

The actual "is there anything wrong" logic is fine, but the list of
clashing values set for a given record is not.

Unfortunately this also doubles the time the test takes, to
21 seconds on MacOS. OW.
2021-09-13 16:25:15 -05:00
seebs
0d568b0d52
Merge pull request #1687 from seebs/core850
make details optional and support limits on mutex checks
2021-09-09 16:17:53 -05:00
Seebs
e27085da66 check context occasionally while processing mutex check results
It's hard to do this remotely sanely for the fragments, but the
translation and collation process itself could be fairly slow on
large data sets, so we should check occasionally for canceled
context and return early if no one needs the result anyway.

Also, take out no-longer-correct comments from the test case.
2021-09-08 13:47:15 -05:00
Seebs
26d38c0ee0 make details optional and support limits on mutex checks
We support query parameters for details (default false) which
request additional data, and for a limit (default 0/MaxInt32)
on number of results returned to limit the amount of spam
produced if there's a lot of results. The simpler default
output should reduce load and runtime significantly, and the
ability to specify limits makes it easier to get reasonably
small responses.

There's some context support here, but the underlying filters
don't take contexts or check for them, which is probably
a flaw but might be a bit large to correct for this.
Despite being large, this set of changes is actually
fairly well contained within the mutex-checking code.
2021-09-08 11:59:47 -05:00
Ben Johnson
484fcd8cf2
Merge pull request #1684 from molecula/sql-select
CORE-807: Implement non-aggregate SELECT query
2021-09-08 08:26:25 -06:00
Ben Johnson
92646cbdf7 Implement non-aggregate SELECT query 2021-09-08 08:09:54 -06:00
seebs
1586861ed2
Merge pull request #1685 from seebs/fewerSlowTests
drop rbf_bolt tests from CI
2021-09-07 16:41:17 -05:00
Seebs
37b55c190f drop rbf_bolt tests from CI
The rbf_bolt tests are unusually expensive, partially because they're
run with the race detector on, but also because it's basically running
two copies of all the tests and comparing them... But they haven't
detected anything in ages, because the RBF stuff is now pretty stable,
and those tests take about twice as long as anything else in our testing,
and thus impede our workflow noticably for little-to-no return. We might
some day want to fully remove them, but for now, just taking them out of
CI should streamline our workflows a bit.
2021-09-07 14:06:23 -05:00
seebs
a3368c64ab
Merge pull request #1681 from seebs/core850
mutex sanity-check endpoints to allow for checking possible mutex corruption
2021-09-07 14:02:44 -05:00
seebs
7586cc0724
Merge branch 'master' into core850 2021-09-07 13:11:31 -05:00
seebs
674fbadd0f
Merge pull request #1680 from seebs/mutexFixes
Mutex fixes -- these address a couple of cases in which mutexes could end up with duplicate values, and also improve the testing so they're more likely to get caught.
2021-09-07 13:11:22 -05:00
tgruben
2a3a5285de
Merge branch 'master' into mutexFixes 2021-09-07 12:45:04 -05:00
Seebs
b391ab9153 mutex sanity-check
This implements a fairly straightforward sanity-check for mutexes,
implemented as a bitmapfilter at the fragment level, and with higher
levels combining results. There's two endpoints, an internal endpoint
which only checks the local node's shards, and an external one which
forwards requests (using the internal endpoint) to all the other nodes.

The internal endpoint does not do key translation, the external one
does.

The transmission format is a probably-inefficient JSON blob, and
returns data separated per-shard so we don't have as much merging
work to do.

This introduces a horrifying monstrosity function which tries to
sneakily corrupt mutex fields and which has to be exported (EWWWWW)
but which is only present in _test code (!??!! THIS WORKS WHY).

Also one typo fix in unrelated code caused by not wanting to keep
fighting with gofmt about this.
2021-09-07 12:41:49 -05:00
rachithrr
5ae2abcfaa
Merge pull request #1682 from rachithrr/ingesttool
CORE-747: Build tooling to provide datagen-like functionality that uses the API
2021-09-03 12:55:55 -04:00
tgruben
170dda1145
Merge branch 'master' into ingesttool 2021-09-03 09:11:25 -05:00
rachithrr
43b34c7d84 CORE-747: Build tooling to provide datagen-like functionality that uses the API
Featurebase
2021-09-02 10:18:50 -04:00
Seebs
0701f9b7dd fix broken intersectionCallback functions
Two of the intersectionCallback functions were broken.

In intersectionCallbackArrayArray, when checking to see whether we can
skip ahead 8, we need to check whether that last value is lower than
the one we're looking for, not whether the first value is.

For intersectionCallbackArrayBitmap, actually implement it at all;
it had never gotten modified significantly from the original
intersectionCount, so it still counted and returned intersections, but
never called the callback at all.
2021-08-31 13:45:59 -05:00
Seebs
6dc8cd7b49 improve mutex import testing
When doing the import tests, import all the data sets if there's
multiple data sets, and check that we're producing the correct number of
results including overwriting previous values, not just that we produce
the same number of values that we set, which shouldn't happen if there's
any overlap.

Also add a specific test that triggers the case I first ran into this for.
2021-08-30 14:16:15 -05:00
Ben Johnson
408e3f84b3
Merge pull request #1679 from molecula/sql-where
CORE-808: Handle SQL WHERE clause
2021-08-26 08:44:15 -06:00
Ben Johnson
6bf854862b Handle SQL WHERE clause 2021-08-26 08:25:16 -06:00
seebs
397f90896b
Prototype ingest API
This is the prototype of the new JSON ingest API. It's not for external use yet, it's still experimental.
2021-08-20 13:26:36 -05:00
Seebs
bb1d52a385 ingest and ingest/codec testing work
This is a design to let us write test cases for ingest with schema setup
and data in the json formats we want to use, and results as alternating
queries and expected results, so we can just create new test files and
run the tests against them. We also have to report back what we created
when creating things.

In the process of developing this, I noticed that the documentation describes
ingest schema as allowing more than one schema operation, but we didn't support
this, and also it wouldn't do much good because there was no way to do partial
things like "just add a field". Fixed.

Also we implement comparison for ops, so the test output is actually
a test rather than just some data to visually eyeball.

In the process, realize that the handling of timestamps was wrong; we said that we
take them as raw numbers relative to the epoch, not as raw Unix timestamps.

Also a couple of related cleanups caught by doing the testing.
2021-08-19 09:50:59 -05:00
nagamocha3000
3185fe4181 Add schema endpoint
This adds the schema and ingest endpoints. (Code actually by Brandon,
seebs just squashed the commits.)
2021-08-19 09:50:59 -05:00
Seebs
e167f1c7fa fancier shard-sorting
This is a rework of Nia's radix sort. Still using stdlib sort for the
tail ends of things, and should probably replace it at some point
because it's still woefully inefficient, but this gets decent
performance, and lets us do the fancy thing of doing quick partial
sorting by record-key-only to get to shards, then deciding whether
to sort by value-then-record (as for a set field) or just by record
(as for int fields), which lets us reduce the amount of re-sorting
the same data by different criteria we do.

We also use a messy code-duplication basically-bubblesort for the
inner loops because it's much cheaper for small N.

This also lets us use field-aware sorting for shards, sorting them
correctly for a corresponding field type, and add corresponding API
support and fragment support for an option to tell the fragment
code that we already ordered things in the order that's most
efficient there, to avoid a second sort that we don't otherwise
need.
2021-08-19 09:50:59 -05:00
Seebs
016765d8a2 Prototype ingest API
This partially-implemented prototype of the ingest API is based on our
programmatic ingest API reference. It has noticable limitations, most
crucially that it doesn't handle multi-node clusters right now. However,
it basically implements the expected semantics.

There's some noticeable performance issues to do with the high overhead
of sorting bits in order to import them efficiently, but this is fixable.

We also add the hooks to the internal client, and make the finisher logic
a bit smarter.

Much of this code was originally by Nia Weiss, but it's been merged
and restructured a bit to get things broken into logical commits.
2021-08-19 09:50:59 -05:00
Matthew Jaffee
61f3fa23b0
Merge pull request #1676 from seebs/prep
ingest API prep work
2021-08-19 09:08:28 -05:00
Seebs
423cddbdbb avoid allocations in viewsByTime
This is sort of horrible, but viewsByTime was about 25% of total CPU time in
the ingest path, NOT including increased GC overhead. This overoptimized
approach to letting us recycle a buffer, and use the same buffer for multiple
time views at once, reduces that to about 2.5%. Sorry for the mess.

We also streamline the process of building the per-view data sets a bit,
and streamline it a lot in the non-time-quantum case.
2021-08-18 13:45:36 -05:00
Seebs
f019cc7409 make import correctly reflect that it needs a single shard always
In fact, we have a number of things assuming that values passed to Import
always fit within a single known shard, so, drop all the extra complexity
around this, drop the computation of fancy view/shard keys, and so on.

There's a lot of room left to improve this probably but it's at least
better, I think.

Unfortunately, there's a handful of things, basically all of which are
test cases, which were relying on this, so, we also add functionality
for splitting import requests by shards. But this allows us to stop
duplicating each shard's inputs one at a time... which turns out to
mean that we now care that the import operation can write back to the
import request. This only affects test cases, so we adopt a crufty
hack involving cloning import requests in those rare cases, and also
when reusing the same column IDs to write to the existence field that
we'd be using later to write to another field.

Note that even if we weren't overwriting the column IDs with positions,
we'd be sorting the column/row ID lists by row-then-column, which means
we'd still be corrupting the column ID lists. This may want to change
at some point.

We also reuse a single Tx for all the views, because DB-per-shard
means that should work fine, and reduces the cost of doing these
updates, probably.
2021-08-18 13:45:36 -05:00
Seebs
6af987a5ba fix error formatting/spelling
Go convention is that error messages don't end with periods and
don't start with capital letters.
2021-08-18 13:45:36 -05:00
Seebs
ab9b70d7e8 mapperLocal: actually leave loop on read from done channel
staticcheck points out that the break is otherwise an ineffective
break because it just ends the current case clause of the switch
it's in, which is true.
2021-08-18 13:45:36 -05:00
Seebs
1745a93aee allow "us" for microseconds in timestamp units
The convention of using a "u" for "micro" is pretty well-established and some
people will have trouble typing the Greek letter, accept that as a synonym.
2021-08-18 13:45:36 -05:00
Seebs
e768fc89ea stop using pointers to time.Time
We're reading timestamps as []int64, instead of allocating a time.Time
for each timestamp, just use the same logic to determine whether to use the
int64 timestamp that we would have used to decide whether to allocate it.
We still have to check the whole run, though, because we're providing a large
list of 0s instead of "no timestamps", for Reasons.
2021-08-18 13:45:36 -05:00
Seebs
35faa39b20 don't use nil qcx
A nil Qcx is a crime against existence and makes baby pandas cry.

Having taken out the hack that tried to accommodate this when tests did it,
we now have to fix the tests. Oh no.
2021-08-18 13:45:36 -05:00
Seebs
dab8dff9c2 make "subdivide list by shardwidth" available for reuse
We keep wanting this, and it's shardwidth-dependent code, and we keep rewriting it.
It should be in the shardwidth package.
2021-08-18 13:45:20 -05:00
Seebs
7b27a48d7c allow Molecula copyrights 2021-08-17 15:23:31 -05:00
Ben Johnson
409d59e297
Merge pull request #1675 from molecula/sql-count
CORE-806: Implement basic SQL COUNT(*) query
2021-08-17 14:12:40 -06:00
Ben Johnson
702f55964f Add apt-get update flag 2021-08-17 07:21:40 -06:00
Ben Johnson
5122c2decc Refactor SQL planner to inside Server 2021-08-16 13:12:16 -06:00
Ben Johnson
9b8dc3d7e6 Implement basic SQL COUNT(*) query 2021-08-13 10:41:39 -06:00
Matthew Jaffee
dac6234d0d
Merge pull request #1671 from jaffee/differentiate-map-error
differentiate error messages between opening file and mapping it
2021-08-09 12:27:22 -05:00
Matthew Jaffee
207634aea3 differentiate error messages between opening file and mapping it 2021-08-09 11:42:25 -05:00
Matthew Jaffee
54a4c2a587
Merge pull request #1663 from molecula/fully-disable-usage-endpoint
CORE-800 Disable /ui/usage endpoint completely when usage-duty-cycle is set to 0
2021-08-05 09:37:10 -05:00
Alan Bernstein
9565620f4d Disable /ui/usage endpoint completely when usage-duty-cycle is set to 0 2021-08-04 16:22:55 -05:00
Alan Bernstein
51cc29364c
Merge pull request #1669 from molecula/feature/syang/aggregate-sort
CLOUD-61: Add aggregate sort option to query builder
2021-08-02 20:46:58 -05:00
Stephanie Yang
1609582ba1 Update aggregate label to cardinality 2021-08-02 19:01:37 -05:00
Stephanie Yang
97df326ac6 update test and add additional test for aggregate sort 2021-08-02 19:01:37 -05:00
Stephanie Yang
b0633898a3 add ability to set an aggregate sort on int fields 2021-08-02 19:01:37 -05:00
Ben Johnson
009f4d6d71
Merge pull request #1668 from molecula/extract-max-memory
CORE-473: Add max memory limit to Extract() to prevent OOM
2021-08-02 15:44:27 -06:00
Ben Johnson
60d534c505 Limit translation memory & add max query memory config 2021-08-02 15:28:00 -06:00
Ben Johnson
d16978f5dc Add max memory limit to Extract() to prevent OOM
This commit changes the Extract() query to return an error if the
result set gets too large in order to prevent out-of-memory (OOM)
panics.
2021-08-02 08:20:12 -06:00
Stephanie Yang
317f1e0145
Merge pull request #1665 from molecula/refactor/syang/query-builder
CLOUD-136: Refactor query builder
2021-07-30 09:52:45 -05:00
Stephanie Yang
2947583a95 fix issue with editing saved queries 2021-07-29 12:03:32 -05:00
Stephanie Yang
8dc2105b63 add clear link for sort 2021-07-28 11:38:13 -05:00
Stephanie Yang
d8ac3251f6 replace old query builder 2021-07-28 11:21:54 -05:00
Stephanie Yang
fa353faf72 initial refactor commit 2021-07-28 11:21:54 -05:00
Alan Bernstein
6935ac2667
Merge pull request #1664 from molecula/fix-apt-404
Add apt-get update to dockerfile
2021-07-27 13:52:31 -05:00
Alan Bernstein
a7654ee750 Use -y for apt-get command 2021-07-27 10:21:08 -05:00
Alan Bernstein
9e56335ff9 Add apt-get update to dockerfile 2021-07-26 17:37:39 -05:00
Mahesh Arumugam
abb9b930bf
Merge pull request #1662 from molecula/rowcache-race-again
need to create rowCache lock at the top... otherwise it does nothing
2021-07-20 11:06:38 -07:00
Matthew Jaffee
0d7f1c49c4 need to create rowCache lock at the top... otherwise it does nothing 2021-07-20 12:15:35 -05:00
Matthew Jaffee
e42c96e996
Merge pull request #1661 from molecula/other-client-rowCache-race
fix other batch client rowCache race
2021-07-20 11:06:05 -05:00
Matthew Jaffee
d2e8c5f773 fix other batch client rowCache race 2021-07-20 10:36:17 -05:00
Matthew Jaffee
e450099579
Merge pull request #1660 from molecula/client-batch-race
Fix data race in batch import client by adding locking around rowCache
2021-07-20 09:40:28 -05:00
Matthew Jaffee
11686cac97 add locking around rowCache to avoid data race 2021-07-20 09:00:49 -05:00
Mahesh Arumugam
547d74b0fc
Merge pull request #1658 from molecula/ma/cloud-109
CLOUD-109 FeatureBase Renaming: changing go.mod module name for featurebase
2021-07-19 15:33:10 -07:00
Mahesh Arumugam
bce6d91618 Merge branch 'master' into ma/cloud-109 2021-07-19 14:42:36 -07:00
Travis Turner
695cb10986
Merge pull request #1656 from travisturner/rename-binary
Rename pilosa binary to featurebase
2021-07-19 16:15:59 -05:00
Mahesh Arumugam
44a5e68b3e fix build issue 2021-07-19 13:47:47 -07:00
Mahesh Arumugam
c14c6afbd3 Merge branch 'master' into ma/cloud-109 2021-07-19 13:27:17 -07:00
Travis
7e718743d2
Rename pilosa binary to featurebase 2021-07-19 15:27:14 -05:00
tgruben
eb9adcdec3
Merge pull request #1657 from tgruben/migrate-to-rbf
[ CORE-733] Migration tool for rbf
2021-07-19 15:08:50 -05:00
Mahesh Arumugam
f51fd2351c Merge branch 'master' into ma/cloud-109 2021-07-19 12:40:35 -07:00
Mahesh Arumugam
faf1f93071 fix clustertests 2021-07-19 12:33:22 -07:00
Mahesh Arumugam
a021412d00 fix clustertests 2021-07-19 12:17:59 -07:00
tgruben
fb7f8a69ea
Merge branch 'master' into migrate-to-rbf 2021-07-19 13:05:16 -05:00
Todd Gruben
be0789beb3 use filepath.join 2021-07-19 12:55:39 -05:00
Todd Gruben
bc0c98cca7 applied ben's suggestions 2021-07-19 12:34:43 -05:00
Alan Bernstein
c1cd1d7e4f
Merge pull request #1648 from molecula/usage-disable
CORE-730 Add logging for and allow disabling usageCache
2021-07-19 11:58:57 -05:00
Mahesh Arumugam
858f889745 FeatureBase Renaming: changing go.mod module name for featurebase 2021-07-19 09:20:30 -07:00
Todd Gruben
023d05aaf9 linter fix 2021-07-16 14:22:14 -05:00
Todd Gruben
3c9e1c74af phase 1 complete all data migrated 2021-07-16 13:44:18 -05:00
Alan Bernstein
6415067200 Make duration print format more readable 2021-07-15 14:22:17 -05:00
Alan Bernstein
60f2893152 Add usageCache logging 2021-07-15 14:22:17 -05:00
Alan Bernstein
46df93c521 Unindent 2021-07-15 14:22:17 -05:00
Alan Bernstein
f1e12567a3 Define some constants for usageCache 2021-07-15 14:22:17 -05:00
Alan Bernstein
b7898b0a22 Allow usage-duty-cycle < 20%, and 0 disables 2021-07-15 14:22:17 -05:00
Stephanie Yang
153dea6e1d
Merge pull request #1655 from molecula/bug/syang/query-console-drop-table
CLOUD-137: Wrap field and table names in backticks for sql queries
2021-07-13 17:36:19 -05:00
Stephanie Yang
fa6e179193 handle table-name.field-name syntax sql in console 2021-07-13 14:05:09 -05:00
Stephanie Yang
97ee1b91ef wrap field and table names in backticks for sql queries 2021-07-13 14:05:09 -05:00
Mahesh Arumugam
12fd95d8cf
Merge pull request #1651 from molecula/ma/cloud-110
CLOUD-110 FeatureBase Renaming
2021-07-13 09:43:32 -07:00
Mahesh Arumugam
2cec88e19d Merge branch 'master' into ma/cloud-110 2021-07-13 09:10:36 -07:00
Travis Turner
3bb2b2ff2b
Merge pull request #1653 from travisturner/metric-names
[CLOUD-108] Update metric names to use "featurebase" prefix
2021-07-12 23:55:53 -05:00
Travis
4b494c3ec3
Update metric names to use "featurebase" prefix
If the `--future.rename` flag is set (to true), this commit will cause
metric names to be prefixed with "featurebase" instead of "pilosa".
2021-07-12 17:51:59 -05:00
Mahesh Arumugam
9958e123fb Merge branch 'master' into ma/cloud-110 2021-07-12 15:02:54 -07:00
Alan Bernstein
9c2454e452
Merge pull request #1654 from molecula/fix-changelog-check
CLOUD-113 Rename repository in github API call
2021-07-12 15:01:29 -07:00
Alan Bernstein
27995ffb7b Rename repository in github API call 2021-07-12 14:43:35 -07:00
Mahesh Arumugam
48fcb3a198 FeatureBase renaming: version info in server log 2021-07-12 12:25:43 -07:00
Mahesh Arumugam
2f31ef17e2 VersionInfo 2021-07-09 19:45:54 -07:00
Mahesh Arumugam
eb1cc304cf FeatureBase Renaming: EnvPrefix 2021-07-09 14:52:40 -07:00
Travis Turner
1f04a8d1fe
Merge pull request #1650 from travisturner/cloud-124
[CLOUD-124] Add feature flag --future.rename to support rename to FeatureBase
2021-07-08 14:43:19 -05:00
Travis Turner
1809636319
improve help text
Co-authored-by: Alan Bernstein <alanaaronbernstein@gmail.com>
2021-07-08 13:53:06 -05:00
Travis
3c7ee11ff3
Add feature flag --future.rename to support rename to FeatureBase
This commit adds a `Future` scope to the configuration options, and for
the time being includes a single flag within that scope: `rename`.

Usage:
--future.rename

The value is a boolean available internally at: m.Config.Future.Rename
2021-07-08 13:18:43 -05:00
Stephanie Yang
c9cb87130d
Merge pull request #1645 from molecula/feature/syang/groupby-sort
CLOUD-60: Add ability to sort when building GroupBy queries
2021-07-05 22:30:38 -05:00
Stephanie Yang
9c8b272bb0 fix secondary sort field for sum case 2021-07-02 16:10:10 -05:00
Stephanie Yang
986f1f1d0f clear sort when resetting 2021-07-02 16:10:10 -05:00
Stephanie Yang
46016fce4a add sort option to GroupBy query builder 2021-07-02 16:10:10 -05:00
Stephanie Yang
383b0a69d1 fix group by fields stuff 2021-07-02 16:10:10 -05:00
tgruben
37bb8dee0e
Merge pull request #1649 from tgruben/fix-backup
change alpine install to ubuntu
2021-07-02 15:03:21 -05:00
tgruben
d4efa08c2d
Merge branch 'master' into fix-backup 2021-07-02 14:37:31 -05:00
Todd Gruben
bf26aa9d57 change alpine install to ubuntu 2021-07-02 14:36:23 -05:00
tgruben
7740036717
Merge pull request #1647 from tgruben/core-527
[CORE-527] multi-node to single backup check
2021-07-01 15:17:19 -05:00
Todd Gruben
4739ebf79e multi-node to single backup check 2021-07-01 14:02:16 -05:00
tgruben
69ef605f93
Merge pull request #1646 from tgruben/ci-backup
[CORE-629] CI test for backup restore
2021-07-01 09:55:50 -05:00
Todd Gruben
2f4f75a6cb renamed docker compose image 2021-07-01 08:56:41 -05:00
Todd Gruben
039ebc7ea6 trying docker login 2021-06-30 16:56:57 -05:00
Todd Gruben
74c03b1a33 needed executor 2021-06-30 15:02:22 -05:00
Todd Gruben
bac9ac047c Merge branch 'ci-backup' of github.com:tgruben/privilosa into ci-backup 2021-06-30 14:59:05 -05:00
Todd Gruben
87d2b513d8 corrected ci config 2021-06-30 14:58:39 -05:00
tgruben
72b2896178
Merge branch 'master' into ci-backup 2021-06-30 14:55:59 -05:00
Todd Gruben
3f8047778c CI test for backup restore 2021-06-30 14:52:15 -05:00
Nia
15c6023806
Merge pull request #1643 from seebs/keepInTranslation
[CORE-727] separate backup of index data and index translation keys
2021-06-30 13:39:05 -04:00
Nia
bc01e55280
Merge branch 'master' into keepInTranslation 2021-06-30 13:11:58 -04:00
Nia
37f291bb5b
Merge pull request #1644 from niaow/backup-dir-fsync
[CORE-726] fsync all directories after completing a backup
2021-06-30 13:11:49 -04:00
Seebs
90c424a4d9 separate backup of index data and index translation keys
It's not enough to back up each index's translation keys after
backing up that index's data; we also have to back them up after
backing up any index data from indexes which have foreign key
references to that index. So we do the per-index passes separately.

Since the individual backup data files are being created separately,
the expected output is unchanged for a quiescent database, the only
difference is that the amount of translation info which might be
newer than the data stored for shards is potentially increased.
2021-06-30 11:46:47 -05:00
Nia Weiss
779e27dcf6
fsync all directories after completing a backup
Previously the backup tool only fsync'ed the files.
Since the directories were not synced, it was possible for the references to be lost.
Now we sync the entire output directory tree and its parent.
2021-06-30 12:39:17 -04:00
tgruben
a8161923de
Merge pull request #1642 from tgruben/index-delete-shard
delete index missed index/shard removal [Bug]
2021-06-25 12:10:08 -05:00
tgruben
b15b11462a
Merge branch 'master' into index-delete-shard 2021-06-25 11:26:31 -05:00
Todd Gruben
ccda5f46d5 delete index missed index/shard removal 2021-06-25 11:24:28 -05:00
Mahesh Arumugam
5187d3f862
Merge pull request #1641 from molecula/ma/cloud-119
CLOUD-119 CORE-653 Fix percentile query
2021-06-24 17:45:07 -07:00
Mahesh Arumugam
357caf68c3 Fix percentile query: field is mandatory (should not crash), fieldnames can be unquoted 2021-06-24 15:10:05 -07:00
seebs
3a678c9ce0
Merge pull request #1639 from molecula/ciFailures
address CI failures due to timeouts
2021-06-24 11:11:10 -05:00
seebs
965a325f9d
Merge branch 'master' into ciFailures 2021-06-24 09:48:06 -05:00
tgruben
69dc3593a5
Merge pull request #1640 from tgruben/chksum
chksum sub-command for easier data validation
2021-06-23 16:38:44 -05:00
Todd Gruben
44281fa5c2 add chksum command for easier data validation 2021-06-23 16:10:52 -05:00
Seebs
0e1d448baa explicitly revoke lease on shutdown
If we explicitly shut a node down, we don't want everyone else
thinking it's up for the next 5 seconds. Worse, in CI, we have random
long delays (10+ seconds) with no CPU activity at all, so we have to
set the TTL longer there. Which makes any test checking for responsive
detection of a node going down take even longer. So! We revoke
leases on our way down, and this makes the tests not take so
long, and allows us to have a reasonable timeout on the test, while
having a completely unreasonable HeartbeatTTL to make CI stop
breaking randomly.
2021-06-22 09:02:25 -05:00
Seebs
13dd357ddd bump heartbeatTTL to ludicrous value (60s) for testing
After continuing to see weird test failures, did some more careful testing,
discovered that CI can pause a machine entirely for up to 29 seconds
or so very rarely, and 5-10 seconds quite frequently, which causes
cascading heartbeat failures and so on. Remove those.
2021-06-22 09:02:25 -05:00
Seebs
5898c58a80 try to force TMPDIR to be the ram disk
CircleCI is providing a ramdisk as /mnt/ramdisk. Using the ramdisk
instead of local storage makes fsync operations essentially free,
which removes (some of) the frequent multi-second delays we see during
runs otherwise.
2021-06-22 09:02:25 -05:00
Seebs
01103b26f0 make etcd bootstrap timeout configurable
It turns out that it's desireable to be able to configure the bootstrap
timeout for etcd, because during startup, we end up delaying that long
(N-1) times in series during each cluster creation, which is pointless
when we're starting the whole cluster. Reduces test runtime by several
minutes.
2021-06-22 09:02:25 -05:00
Ben Johnson
e8a3c313ac
Merge pull request #1638 from molecula/parallelize-restore
CORE-640: Parallelize restore command
2021-06-21 15:07:58 -06:00
Todd Gruben
23ba86cbfc linter fix 2021-06-21 14:15:13 -05:00
Ben Johnson
dad2372a8c CORE-640: Parallelize restore command 2021-06-18 16:03:38 -06:00
Ben Johnson
e082f6bce0
Merge pull request #1637 from molecula/parallel-backup
CORE-639: Parallelize backup
2021-06-15 17:44:17 -06:00
Ben Johnson
3df1f2d094 CORE-639: Parallelize backup 2021-06-15 16:55:05 -06:00
Samir Patel
f5844a0eb3
Merge pull request #1633 from 54mir/reset-cache-on-schema
CORE-642 Reset Usage Cache If Outdated On Request
2021-06-15 13:01:58 -05:00
Samir Patel
92ff74c72d
Merge branch 'master' into reset-cache-on-schema 2021-06-15 10:32:43 -05:00
Samir Patel
6b45325ca7 expand comment on duty cycle 2021-06-15 09:37:42 -05:00
Samir Patel
fb11d7f656
Update api.go
Co-authored-by: Alan Bernstein <alanaaronbernstein@gmail.com>
2021-06-15 09:17:53 -05:00
Stephanie Yang
25bf4fdaa7
Merge pull request #1636 from molecula/feature/syang/diskusage-lastupdated
CLOUD-78: Add 'last updated' info to tables UI
2021-06-14 16:25:22 -05:00
Stephanie Yang
7c89eb8033 add cache refresh copy 2021-06-14 16:02:15 -05:00
Stephanie Yang
9c21f6f109 consistency 2021-06-14 15:49:20 -05:00
Stephanie Yang
b14811b4fe add UTC time tooltip when hovering ov er relative time 2021-06-14 15:47:09 -05:00
Stephanie Yang
f48d7998e1 add last updated info for disk usage to ui 2021-06-14 15:47:09 -05:00
Stephanie Yang
e4159a1927 fix UI blow up when index disk usage not available 2021-06-14 15:47:09 -05:00
Ben Johnson
ee3a7a845e
Merge pull request #1635 from molecula/backup-dir
CORE-638: Refactor backup/restore to use directory archive
2021-06-14 11:03:39 -06:00
Samir Patel
d83a502657 change comment 2021-06-14 11:55:23 -05:00
Samir Patel
bfc90d148d Merge branch 'reset-cache-on-schema' of github.com:54mir/pilosa into reset-cache-on-schema 2021-06-14 11:53:46 -05:00
Samir Patel
6bdf685471 change waitMultiplier to float64 2021-06-14 11:43:49 -05:00
Samir Patel
11207fc589
Update api.go
Co-authored-by: Alan Bernstein <alanaaronbernstein@gmail.com>
2021-06-14 11:12:12 -05:00
Samir Patel
8bf472bb75 add duty cycle config flag 2021-06-14 10:48:52 -05:00
Ben Johnson
73f0668fe1 Refactor backup/restore to use directory archive 2021-06-14 09:43:20 -06:00
Samir Patel
011291f19b update comments 2021-06-11 11:28:39 -05:00
Samir Patel
76b899ef82 Merge branch 'reset-cache-on-schema' of github.com:54mir/pilosa into reset-cache-on-schema 2021-06-11 11:24:49 -05:00
Samir Patel
b46b5fc134 remove usage-interval flag 2021-06-11 11:16:32 -05:00
Samir Patel
39c9b7c61a
Merge branch 'master' into reset-cache-on-schema 2021-06-10 18:33:33 -05:00
Samir Patel
268e710e69 update comment 2021-06-10 17:36:03 -05:00
Samir Patel
9b11ded9e3 scale refresh rate by last calculation time 2021-06-10 16:30:22 -05:00
Kuba Podgórski
5013204b6d
Merge pull request #1634 from kuba--/core-649
[CORE-649]: Add support for timestamps in pg writer
2021-06-10 23:28:05 +02:00
Kuba Podgórski
b218901fae Add support for timestamps in pg writer 2021-06-10 21:58:08 +02:00
Stephanie Yang
8f3c4705cc
Merge pull request #1631 from molecula/chore/syang/querybuilder-cleanup
CLOUD-76: Add support for single codepoint keys for like queries
2021-06-10 11:45:33 -05:00
Samir Patel
a7c24c6745 lock read of lastUpdated 2021-06-10 11:28:23 -05:00
Stephanie Yang
db018e5f41 Add support for single codepoint keys for like queries 2021-06-10 11:03:15 -05:00
Stephanie Yang
1bd872e1f4 make keys optional on RowCallType 2021-06-10 11:03:15 -05:00
Samir Patel
486244ab58 reset cache if outdated on call 2021-06-10 10:48:44 -05:00
Nia
d12e4e9f25
Merge pull request #1632 from niaow/fix-time-keys
[CORE-579] Fix batch import of time fields with key translation
2021-06-10 11:29:55 -04:00
Nia Weiss
539d1ffe6b
fix batch import of time fields with key translation
Time fields were not listed as a type which could accept key translation, causing the translation code to fail.
This also adds tests for keyed time and mutex fields.
2021-06-10 09:41:59 -04:00
Stephanie Yang
4baffff847
Merge pull request #1630 from molecula/feature/syang/querybuilder-types
CLOUD-77: Allow all field types for query builder
2021-06-07 20:19:26 -05:00
Stephanie Yang
90d795cc69 update stringifyRowData tests 2021-06-07 17:23:42 -05:00
Stephanie Yang
cc624a9c18 add support for non-keyed set, time, mutex and decimals 2021-06-07 17:23:42 -05:00
Travis Turner
22d46a8afa
Merge pull request #1623 from molecula/feature/syang/querybuilder-like
CLOUD-76: Allow `like` for query builder queries
2021-06-07 17:18:34 -05:00
Stephanie Yang
732040dc80 update like to wrap between % if no wildcard is given 2021-06-07 16:30:39 -05:00
Stephanie Yang
af83e61101 add tests 2021-06-07 16:30:39 -05:00
Stephanie Yang
64c0542c3e implement 'like' for query builder queries 2021-06-07 16:30:39 -05:00
Nia
e6644d25d2
Merge pull request #1626 from niaow/fix-keys
[CORE-579] Standardize key translation on the find and create methods
2021-06-07 16:17:41 -04:00
Kuba Podgórski
118961b911
Merge branch 'master' into fix-keys 2021-06-07 21:21:31 +02:00
Kuba Podgórski
c2a0bba99c
Merge pull request #1629 from kuba--/core-531
[CORE-531]: Additional logging for LookupDB connection
2021-06-07 21:16:49 +02:00
Nia Weiss
c2f58f7af0
fix column key translation test
It previously checked hardcoded values.
This does not work due to shard width differences.
2021-06-07 14:52:04 -04:00
Nia Weiss
39337fa41b
fix shadowing of require in client internal tests
The `require` tool was being shadowed with the outer test's T, causing the testing package to explode sometimes.
2021-06-07 14:52:04 -04:00
Nia Weiss
c0ef297b11
standardize key translation on the find and create methods
This migrates existing code from the old TranslateKey(s) endpoints to the newer CreateKeys and FindKeys endpoints.
The CreateKeys and FindKeys endpoints were created previously as the TranslateKeys endpoint had no way to behave sanely when the looked-up key did not exist (the parallel-arrays representation did not have a good way to represent a missing key).
This change also removes the old TranslateKey(s) functions from the translation stores.
It leaves a wrapper emulating the TranslateKey(s) endpoints so that old idk still works for now.
2021-06-07 14:47:52 -04:00
Kuba Podgórski
46fbde4f0b Update holder.go 2021-06-07 18:41:13 +02:00
Samir Patel
b886d1e571
Merge pull request #1622 from 54mir/lattice-fix
CORE-557 UI/Usage Cache with Lattice Fix
2021-06-04 12:12:34 -05:00
Samir Patel
5ef218977f
Merge branch 'master' into lattice-fix 2021-06-04 10:16:46 -05:00
nagamocha3000
3b6ba01111
Merge pull request #1628 from nagamocha3000/delete-id-allocs
Delete ids allocated for index if any present
2021-06-04 16:51:32 +03:00
tgruben
6f06a6cba3
Merge branch 'master' into lattice-fix 2021-06-04 07:36:24 -05:00
nagamocha3000
a904d9e68e Delete ids allocated for index if any present 2021-06-04 14:34:48 +03:00
Stephanie Yang
e1394c2bdb
Merge pull request #1612 from molecula/feature/syang/groupby-filter
CLOUD-59: Updates saved query list for GroupBy filter
2021-06-03 16:57:22 -05:00
Stephanie Yang
3801d4b072 add gitignore to lattice folder 2021-06-03 16:40:10 -05:00
Stephanie Yang
c1915ff361 filter out saved queries without rowCalls 2021-06-03 16:40:10 -05:00
nagamocha3000
29002b3f62
Merge pull request #1624 from nagamocha3000/fix-percentile-overflow
Fix percentile overflow error
2021-06-04 00:24:19 +03:00
nagamocha3000
b1d18a1ba3 Make percentile checker in test-case match executor implementation 2021-06-03 22:14:05 +03:00
nagamocha3000
af83205032 Fix percentile overflow error 2021-06-02 21:28:07 +03:00
Samir Patel
883fa9ac0b replace sleep with after in select 2021-06-01 21:24:08 -05:00
Samir Patel
15ef157779 remove comment 2021-06-01 20:50:55 -05:00
Samir Patel
2e08b15620 remove lastupdate log to console 2021-06-01 20:48:44 -05:00
Samir Patel
9608c0c2cb move trigger to inside refresh fn 2021-06-01 20:48:12 -05:00
Samir Patel
81f1606242 poll places in indexDetails to check for closing 2021-06-01 20:47:53 -05:00
Samir Patel
041ae01da1 poll places in usage calculation to check for closing 2021-06-01 20:46:44 -05:00
Samir Patel
a9079815b2 remove prints 2021-06-01 14:45:52 -05:00
Samir Patel
6a8bf3acd6 stops calculation on server close 2021-06-01 14:34:51 -05:00
Samir Patel
edf71c1bf7 update comment and remote print 2021-06-01 10:47:10 -05:00
Samir Patel
5437a11216 remove prints 2021-06-01 10:47:10 -05:00
Samir Patel
660c6d10ca rename locks and remove prints 2021-06-01 10:47:10 -05:00
Samir Patel
017d012d51 change lock order 2021-06-01 10:47:10 -05:00
Samir Patel
20b721ad9d add wait group 2021-06-01 10:47:10 -05:00
Samir Patel
81413c4f0a Remove recalculation on new index 2021-06-01 10:47:10 -05:00
Samir Patel
4ac7f6e154 check error from ResetCache 2021-06-01 10:47:10 -05:00
Samir Patel
a5ae6c15fc add locks 2021-06-01 10:47:10 -05:00
Samir Patel
5f46635094 add channel to Refresh goroutine 2021-06-01 10:47:10 -05:00
Samir Patel
0810273ea1 reset cache before test and add test conditions 2021-06-01 10:47:10 -05:00
Samir Patel
fcdefe8bb6 add ability to reset cache 2021-06-01 10:47:10 -05:00
Samir Patel
468a288b72 remove print 2021-06-01 10:47:10 -05:00
Samir Patel
a7620012fa adjust locking 2021-06-01 10:47:10 -05:00
Samir Patel
4b7e0e9194 move where cache updates lastUpdated val 2021-06-01 10:47:10 -05:00
Samir Patel
abcd90b60a remove print statements 2021-06-01 10:47:10 -05:00
Samir Patel
4e2727c255 revert txfactory to original 2021-06-01 10:47:10 -05:00
Samir Patel
3e81406ab0 clean test case and add comments 2021-06-01 10:47:10 -05:00
Samir Patel
eff3b25b97 change test case to reflect cache loading before test 2021-06-01 10:47:10 -05:00
Samir Patel
fe0bb20658 remove intentional failure 2021-06-01 10:47:10 -05:00
Samir Patel
53b0e98bb1 add while loop to wait for holder to populate 2021-06-01 10:47:09 -05:00
Samir Patel
5cbf828588 adjust timing 2021-06-01 10:47:09 -05:00
Samir Patel
8824dddc3a add debug statements 2021-06-01 10:47:09 -05:00
Samir Patel
a0ba9327f7 play with timing 2021-06-01 10:47:09 -05:00
Samir Patel
dbdd3c4998 see if this is the only test failing 2021-06-01 10:47:09 -05:00
Samir Patel
fd58fe1a7d test stuff 2021-06-01 10:47:09 -05:00
Samir Patel
63300db1bd try test with usage always blocking on calc 2021-06-01 10:47:09 -05:00
Samir Patel
108da005b7 test stuff 2021-06-01 10:47:09 -05:00
Samir Patel
f946528053 comment out debug statements 2021-06-01 10:47:09 -05:00
Samir Patel
7799d7c680 Add sleep to wait for holder to load 2021-06-01 10:47:09 -05:00
Samir Patel
f6d7d1af39 move requestNodes() out of refresh loop 2021-06-01 10:47:09 -05:00
Samir Patel
0b083da126 debugging test 2021-06-01 10:47:09 -05:00
Samir Patel
1e5df36fb7 change to not calculate node usage periodically 2021-06-01 10:47:09 -05:00
Samir Patel
1385cf61eb attempt to address missing node uri issue 2021-06-01 10:47:09 -05:00
Samir Patel
79f04f31cb see if this gets test passing 2021-06-01 10:47:09 -05:00
Samir Patel
21e5cda7e0 Add lock to node usage 2021-06-01 10:47:09 -05:00
Samir Patel
14533d88a1 add read lock 2021-06-01 10:47:09 -05:00
Samir Patel
7d56414557 change err response to info messages 2021-06-01 10:47:09 -05:00
Samir Patel
4096c8cb8e go mod tidy 2021-06-01 10:47:09 -05:00
Samir Patel
e7f1c8b66a Reverted directoryUsage back to using old Readdir() 2021-06-01 10:47:09 -05:00
Samir Patel
ae6687e71b change flag name to usage-interval 2021-06-01 10:47:09 -05:00
Samir Patel
42067237f7 simplify if statement in calcUsage() 2021-06-01 10:47:09 -05:00
Samir Patel
e8b9fa0482 update comments and rename nodeUsage() 2021-06-01 10:47:09 -05:00
Samir Patel
f5cc179893 change flag from interval to duration 2021-06-01 10:47:09 -05:00
Samir Patel
0ef16ce634 fix calculation for nodes 2021-06-01 10:47:09 -05:00
Samir Patel
ff6b3fed97 remove initCache 2021-06-01 10:47:09 -05:00
Samir Patel
431db4c1a3 add 'lastUpdated' in http response 2021-06-01 10:47:09 -05:00
Samir Patel
8ce17f405b rename flag to disk-usage-interval 2021-06-01 10:47:09 -05:00
Samir Patel
9beb3f0b3a rename flag and add default value for flag 2021-06-01 10:47:09 -05:00
Samir Patel
827b125c3c rename and set default 2021-06-01 10:47:09 -05:00
Samir Patel
03e0df389d use flag value as refresh value 2021-06-01 10:47:09 -05:00
Samir Patel
cd47a381f2 use flag value as refresh value 2021-06-01 10:47:09 -05:00
Samir Patel
b02188fd15 update usage cache periodically 2021-06-01 10:47:09 -05:00
Samir Patel
52418df4ba start periodic cache recalculation at startup 2021-06-01 10:47:08 -05:00
Samir Patel
835c63011a add server flag 2021-06-01 10:47:08 -05:00
Samir Patel
be10927ca7 set lastUpdated after cache calculation 2021-06-01 10:47:08 -05:00
Samir Patel
20f8479f41 add time based cache 2021-06-01 10:47:08 -05:00
Samir Patel
11d1859830 undo changes to IndexUsageDetails 2021-06-01 10:47:08 -05:00
Samir Patel
4842d93850 adds logic to remove old items from cache 2021-06-01 10:47:08 -05:00
Samir Patel
d71da09db2 add cache update on time 2021-06-01 10:47:08 -05:00
Samir Patel
713ffb723b replace ReadDir 2021-06-01 10:47:08 -05:00
Samir Patel
155003122b replace ReadDir syscall with new one from 1.16 2021-06-01 10:47:08 -05:00
Samir Patel
c812cca58e add cache 2021-06-01 10:47:08 -05:00
tgruben
3c399bc533
Merge pull request #1621 from tgruben/cluster-restore
[CORE-529] Multi-node restore
2021-05-28 11:36:04 -05:00
Todd Gruben
c16a7a06a0 applied bens suggestions mainly using errgroup 2021-05-28 11:02:31 -05:00
Todd Gruben
35672c53ce added node partition endpoint;cluster aware key restore 2021-05-28 09:27:42 -05:00
Nia
9c7ca2380f
Merge pull request #1620 from niaow/fix-like
[CORE-577] Execute like queries on the primary's key translation database
2021-05-28 07:18:11 -04:00
Nia
a77be9dd61
Merge branch 'master' into fix-like 2021-05-28 06:40:57 -04:00
Alan Bernstein
9ca33abadd
Merge pull request #1610 from molecula/remove-oss-readme
Remove readme content that only applies to the open-source fork
2021-05-27 18:29:45 -05:00
Nia Weiss
a8f7ec4a12
execute like queries on the primary's key translation database
This works around an issue where unreplicated keys will not be matched everywhere.
This also avoids the cost of creating millions of bolt read transactions and allocating strings.
2021-05-27 14:45:10 -04:00
Alan Bernstein
052956daaf Remove readme content that only applies to the open-source fork 2021-05-26 17:13:05 -05:00
Stephanie Yang
bfef27205b
Merge pull request #1618 from molecula/chore/syang/remove-prodpad
CLOUD-75: Remove ProdPad integration
2021-05-26 15:43:23 -05:00
Stephanie Yang
d047c45045
Merge branch 'master' into chore/syang/remove-prodpad 2021-05-26 15:11:05 -05:00
Nia
97fee3b7a8
Merge pull request #1619 from niaow/postgres-delete
[CORE-573] Add an option to open a postgres transaction in lookup
2021-05-26 14:54:06 -04:00
Nia Weiss
a72f6425af
add an option to open a postgres transaction in lookup so it isnt actually a lookup 2021-05-26 14:07:52 -04:00
Alan Bernstein
a94dc50b1c
Merge pull request #1617 from molecula/update-circleci-logic
CLOUD-65 Avoid early exit in 'bash -eo pipefail' script
2021-05-26 12:18:48 -05:00
Stephanie Yang
291a9c1329 remove prodpad integration 2021-05-26 12:09:56 -05:00
Alan Bernstein
daed890f8c Avoid early exit in 'bash -eo pipefail' script 2021-05-26 11:55:44 -05:00
Alan Bernstein
10af6d588f
Merge pull request #1616 from molecula/update-circleci-logic
CLOUD-65 Default output to 'true' in CircleCI job skipping steps
2021-05-26 11:31:20 -05:00
Alan Bernstein
529a325880 Default output to 'true' in CircleCI job skipping steps 2021-05-26 11:00:48 -05:00
Alan Bernstein
90e2d15cf0
Merge pull request #1609 from molecula/more-merge-lattice-stuff
CLOUD-65 Finalize UI merge
2021-05-26 10:43:52 -05:00
Alan Bernstein
58f0f42c1e Add /querybuilder path to statik lattice handler 2021-05-26 10:04:46 -05:00
Alan Bernstein
45dd6dd6bc Remove leftovers from lattice submodule 2021-05-26 10:04:46 -05:00
Alan Bernstein
f51bb0ea43 Update and verbosify job-skipping CI steps 2021-05-26 10:04:46 -05:00
Kuba Podgórski
894f599310
Merge pull request #1613 from kuba--/missed-return
Add return to handleCommitIDs
2021-05-26 16:36:41 +02:00
Kuba Podgórski
1ffafd70eb Add return to handleCommitIDs 2021-05-26 15:43:21 +02:00
Stephanie Yang
17a58f1020
Merge pull request #1608 from molecula/feature/syang/groupby-filter
CLOUD-59: Allow filter parameter query builder GroupBy
2021-05-24 23:06:10 -05:00
Stephanie Yang
3edac67c0c update helper text 2021-05-24 21:44:48 -05:00
Stephanie Yang
2966bb5d66 add helper text for using GroupBy filter 2021-05-24 20:27:58 -05:00
Stephanie Yang
4367f58081 oops 2021-05-24 18:30:09 -05:00
Stephanie Yang
2a4c6d3503 cleanup unused code 2021-05-24 17:06:34 -05:00
Stephanie Yang
fc121f40b2 allow optional filter parameter from saved queries for group by 2021-05-24 16:51:44 -05:00
Mahesh Arumugam
aed8727aea
Merge pull request #1597 from ma-molecula/ma/darwin-arm64
CLOUD-69 add darwin-arm64 support
2021-05-24 12:56:20 -07:00
Mahesh Arumugam
9dc750df97 add .idea to .gitignore 2021-05-24 12:18:56 -07:00
Mahesh Arumugam
f57abbf7fc go version set to 1.16.3 in makefile 2021-05-24 12:17:19 -07:00
Mahesh Arumugam
2679fa6cfd restore import syscall, accidentally removed in previous commit 2021-05-24 12:17:00 -07:00
Mahesh Arumugam
277eba9895 update comment 2021-05-24 12:17:00 -07:00
Mahesh Arumugam
ce2b07b650 move to go 1.16.4 2021-05-24 12:16:57 -07:00
Mahesh Arumugam
b6098f05e6 fixing the build for linux,arm 2021-05-24 12:16:30 -07:00
Mahesh Arumugam
25ddc2d3a0 fixing the build tags 2021-05-24 12:16:28 -07:00
Mahesh Arumugam
0523088fed add darwin-arm64 support 2021-05-24 12:15:48 -07:00
Nia
a0f2623b04
Merge pull request #1607 from niaow/fix-get-translate
Correct handling of field translate data fetch in get translate data endpoint
2021-05-24 13:07:42 -04:00
Kuba Podgórski
ba8d4c4ca1
Merge branch 'master' into fix-get-translate 2021-05-24 18:52:41 +02:00
Kuba Podgórski
01c4b11efb
Merge pull request #1605 from kuba--/fix-file-backup
Fix backup to a file
2021-05-24 18:52:23 +02:00
Kuba Podgórski
a1e7755fe7
Merge branch 'master' into fix-file-backup 2021-05-24 18:29:44 +02:00
Nia Weiss
bfe2383f65
correct handling of field translate data fetch in get translate data endpoint
After retrieving field translation, this attempted to fetch index translation which didn't work because this is not an index translation request.
2021-05-24 12:24:00 -04:00
tgruben
576c2d9efc
Merge pull request #1606 from tgruben/restore-fix
Restore arg handling bug
2021-05-24 11:19:33 -05:00
Todd Gruben
94e66b74b5 tls config bug and arge handling 2021-05-24 11:00:37 -05:00
Kuba Podgórski
be06340869
Merge branch 'master' into fix-file-backup 2021-05-24 16:21:56 +02:00
tgruben
89bf845192
Merge pull request #1600 from tgruben/restore
[ CORE-525] Restore
2021-05-24 09:15:10 -05:00
tgruben
5be61772f0
Merge branch 'master' into restore 2021-05-24 08:51:32 -05:00
Ben Johnson
9cb7c2be6c
Merge pull request #1603 from molecula/fix-bench-filename
Fix benchmark file naming
2021-05-24 07:50:53 -06:00
Todd Gruben
69fda13ff4 cleanup arg processing 2021-05-24 08:48:32 -05:00
Ben Johnson
34bd5c9fa2
Merge branch 'master' into fix-bench-filename 2021-05-24 07:11:17 -06:00
Kuba Podgórski
935edba1db Fix backup to a file 2021-05-24 10:36:58 +02:00
tgruben
b5613a6c33
Merge branch 'master' into restore 2021-05-23 21:18:34 -05:00
Todd Gruben
ff86f82ef2 applied ben's suggestions 2021-05-23 10:27:50 -05:00
Alan Bernstein
9992cb886a
Merge pull request #1599 from alanbernstein/merge-lattice-take2
CLOUD-65 Merge lattice take2
2021-05-21 21:04:54 -05:00
Ben Johnson
69e15525d8 Fix benchmark file naming 2021-05-21 14:51:08 -06:00
Alan Bernstein
e4a8293c0e Update lattice makefile to reflect new structure 2021-05-21 14:56:55 -05:00
Alan Bernstein
4aaf3e2fc2 Copy lattice repo @8c29787 into subdirectory lattice/ 2021-05-21 14:56:55 -05:00
Alan Bernstein
4a00bd9d6e Remove lattice submodule steps from pilosa makefile 2021-05-21 14:56:55 -05:00
Alan Bernstein
89891174b6 Add job skipping step to CI jobs 2021-05-21 14:56:55 -05:00
Alan Bernstein
9ea12803a2 Remove lattice submodule 2021-05-21 14:56:55 -05:00
Todd Gruben
05fea53f73 linter 2021-05-21 09:27:53 -05:00
Todd Gruben
3d577d762a cleanup 2021-05-21 09:27:08 -05:00
Todd Gruben
35f4c33de9 first cache rebuild was ineffective 2021-05-21 09:27:08 -05:00
Todd Gruben
7520e0ef28 rebuild rank caches on restore 2021-05-21 09:27:08 -05:00
Todd Gruben
b25ad81e67 restore without restart 2021-05-21 09:27:08 -05:00
Todd Gruben
cc0c1b829a restore idalloc 2021-05-21 09:27:08 -05:00
Todd Gruben
a1a9103f62 restore column translate keys 2021-05-21 09:27:08 -05:00
Todd Gruben
329f86033d restore field translate keys 2021-05-21 09:27:08 -05:00
Todd Gruben
69245ee209 shard import 2021-05-21 09:27:08 -05:00
Todd Gruben
42b465b80c load schema 2021-05-21 09:27:08 -05:00
Todd Gruben
9d24fb07b7 wired in restore command 2021-05-21 09:27:08 -05:00
Todd Gruben
169dc30d62 api compiles 2021-05-21 09:27:08 -05:00
Todd Gruben
7c6423587a skeleton restore 2021-05-21 09:27:08 -05:00
seebs
b784dd88d9
Merge pull request #1602 from seebs/addgo116
add go 1.16.3 to circleci
2021-05-20 18:43:04 -05:00
Seebs
ac5964480b add go 1.16.3 to circleci
Since we're starting to use this more, add it to the matrix. We should
probably make it our default later, but for now let's just start testing
it.
2021-05-20 17:25:07 -05:00
seebs
2f95bd2de8
Merge pull request #1593 from seebs/getTx
write operations can cause deadlocks in GetTx
2021-05-20 17:09:08 -05:00
Seebs
1c7a6da37b write operations can cause deadlocks in GetTx
The GetTx logic is deeply broken, this DOES NOT fix the underlying
bug.

When any call anywhere in a given set of calls has a top-level write,
we perform all transactions as write transactions, and we do not cache or
share those transactions. This means that anything which causes a
second GetTx for the same index/shard deadlocks against itself.

The two easy to find cases by casual inspection are time quantums
and Not queries, so this addresses those, but this should NOT be
considered a general fix.
2021-05-20 16:41:38 -05:00
seebs
479d668045
Merge pull request #1601 from seebs/noTxBitmap
drop unused TxBitmap
2021-05-20 16:41:18 -05:00
Seebs
7cf0ea452a drop unused TxBitmap
TxBitmap was a workaround for performance problems with doing
individual-bit operations directly on RBF, used only in the
large-writes path of importValue. With importValue no longer
using that path, ever, there are zero remaining users of TxBitmap,
and the test for it no longer exercises it.

Solution: Remove it.
2021-05-20 16:28:19 -05:00
seebs
a46e14ef22
Merge pull request #1598 from seebs/importSpeedups
improve performance of importValue in most cases, switching to consistently use importPositions.
2021-05-20 16:26:38 -05:00
seebs
45255d050f
Merge branch 'master' into importSpeedups 2021-05-20 15:42:11 -05:00
Ben Johnson
4ea655a707
Merge pull request #1596 from molecula/cluster-backup
[CORE-501] Add support for clustered backups
2021-05-20 14:32:23 -06:00
Ben Johnson
94d45a36ed
Merge branch 'master' into cluster-backup 2021-05-20 14:10:27 -06:00
Seebs
4bad5defb6 sort import values stably without using sort.Stable
sort.Stable has horrible runtime -- O(n*logn*logn) -- but if we
don't use sort.Stable, our logic for ensuring that we apply the
"last" value for a given column is actually completely wrong in
the first place.
2021-05-20 12:39:27 -05:00
Seebs
7572acb450 drop "another shard" test as it's probably not valid
We've got a fairly consistent thing of the API splitting data up
into shards before sending it to a field, which it has to do because
of clustering, so we don't intend to support the case where you
have data from another shard in a data set.

Also drop the identical but mislabeled test from TestIntField's
corresponding case.
2021-05-20 12:39:27 -05:00
Seebs
aa4a23b2d9 generate sorted positions from bulkImportStandard
Ensure that positions are sorted, and that we don't generate the same
position more than once.
2021-05-20 12:39:27 -05:00
Seebs
7c4b91eef0 simplify field ImportValue
There's only ever one view in importValue, but there's also only ever
one shard, because importValue is only called by things called from
the API after it has split everything up by shard.
2021-05-20 12:39:27 -05:00
Seebs
d2b925d296 make importValueSmallWrite faster and also the only path
Since we don't always have "snapshots" anymore, the arguable benefit of
avoiding the snapshot is reduced, and the primary expense of
importPositions has been dramatically reduced as well, so let's
just use that all the time, and simplify life.

We also want to make it faster. We don't know how many bits there
are to set or clear in the input set, but we do know exactly how
many bits there are to set AND clear. We can subdivide these into
batches by rows, then process each batch by storing sets at the
bottom and clears at the top. We can also do batches by columns,
reducing the memory overhead of unpacking all the bits at once.

(For extra credit, we could alternate set/clear settings, and
thus do batches of "the clears from row 0, followed by the clears
from row 1" and "the sets from row 1, followed by the sets from
row 2", and so on, but this is too fancy.)

Every caller of importValue is in fact already providing values
with column IDs sorted. As such, we don't need a map for checking
the previously-set columns; we just need to check against the
previous value.
2021-05-20 12:39:27 -05:00
Maxton Huff
741dd2d1ca
Merge pull request #1590 from Maxtonian/longmessage
[CORE-279] Bad query parameters gives error with super long list of shards
2021-05-20 10:40:12 -05:00
Maxton Huff
d9d360aa4d
Merge branch 'master' into longmessage 2021-05-20 10:17:04 -05:00
Maxton Huff
e646d7ac79 wrap mapper error with shards by node 2021-05-20 09:55:42 -05:00
Seebs
bb40d6589f change addOrRemove to not sort inputs
We also implement, but disable for now, a check for sortedness of
inputs. This check was useful in development but it's expensive (about
5% of CPU time for large inputs!) and once we've verified that we
can make it through tests without triggering it, we're probably fine.
2021-05-19 17:36:57 -05:00
Seebs
671a0cf5c6 tweak ImportValue benchmark
With timestamps, we probably want to at least check larger BSI fields,
so we add that. Also, tweak the interpretation of b.N (making each
N count for 10,000 bits) so we can see allocation load at all. But we
also reduce the sparse set to be about one bit per 19 bits, because
if we do one per 70,000, and are doing field-at-a-time imports, we're
getting hundreds of imports to try to match a target of, say, around
a million values.

We also sort the inputs, because ImportValue is about to start requiring
that, since the API does it anyway.

Also, extend this to be available on Fields, because field.ImportValue
is ALSO doing things which could be inefficient or expensive.
2021-05-19 16:40:34 -05:00
Ben Johnson
a4f282c8e8 Allow backup to stdout 2021-05-19 15:04:36 -06:00
Maxton Huff
04bf214f81 remove shard list from mapper error message to avoid duplicate output 2021-05-19 12:20:39 -05:00
Ben Johnson
eb79c35cbd Add support for clustered backups 2021-05-18 15:17:28 -06:00
Nia
ed5359468d
Merge pull request #1592 from niaow/remove-attr
[CORE-421] Remove attributes
2021-05-14 12:34:04 -04:00
Nia Weiss
7fe37a83f4
update license header check exceptions
When moving the protobuf files around, the paths to the generated protobuf files were not updated.
This change updates the paths.
2021-05-14 10:45:46 -04:00
Nia Weiss
f4ba34247f
remove attributes
Attributes are unmaintained and unused.
They have become more of a liability than a benefit.
This change eliminates them from the codebase.
The only user-visible change (assuming that attrs are not used) is that the attrs field will no longer appear in row JSON.
2021-05-14 10:28:08 -04:00
Maxton Huff
53da35eb00 add missing String() calls in error messages 2021-05-13 12:01:12 -05:00
Maxton Huff
63196e7981 add String() to shard slices to reduce error length 2021-05-13 11:39:23 -05:00
Kuba Podgórski
e4be3583d7
Merge pull request #1585 from kuba--/available-shards
[CORE-493] Write remote available shards to etcd, instead of local file.
2021-05-12 18:32:08 +02:00
Kuba Podgórski
79eaae7881
Update field_internal_test.go 2021-05-12 17:02:36 +02:00
Kuba Podgórski
1e6b8434eb
Merge branch 'master' into available-shards 2021-05-11 11:53:35 +02:00
Matthew Jaffee
649ce77dd6
Merge pull request #1589 from jaffee/update-lattice
Update to latest UI including Lookup functionality
2021-05-10 19:46:40 -05:00
Matthew Jaffee
c83099bc8a update lattice submodule, should include all the lookup/postgres changes 2021-05-10 17:29:42 -05:00
seebs
e49192af69
Merge pull request #1580 from seebs/mutexOverwrite
[CORE-533] Improve performance on mutex fields with sparse writes
2021-05-10 15:07:54 -05:00
seebs
82bb067d8e
Merge branch 'master' into mutexOverwrite 2021-05-10 14:48:56 -05:00
Maxton Huff
2467431caf
Merge pull request #1588 from Maxtonian/inspect2
[CORE-459] Investigate- Panic accessing "/inspect" in Molecula 4.1.1
2021-05-10 14:46:39 -05:00
Maxton Huff
e21382fab8 remove handleInspect and inspect validator 2021-05-10 13:14:50 -05:00
Kuba Podgórski
606f664fcc remove unused 2021-05-10 20:02:13 +02:00
Kuba Podgórski
17f89f1bf6 flush bytes instead of roaring 2021-05-10 19:20:34 +02:00
Seebs
130b17b621 don't force immediate recalculate of cache on every update
When writing things that cause additions to the cache, mark it dirty and
flag it for recomputing, but only sometimes actually do the recalculation,
currently implying a 10-second window. We still mark the cache dirty,
so if a request comes in, we'll get fresh data, but the query will be
slowed down because the recomputation will happen then. But that's better
than doing thousands of recalculations which are never used...
2021-05-10 11:58:18 -05:00
Seebs
1e00b50953 gratuitously fancy logic for array/array callbacks
When searching for a small array in a large array, scanning ahead
is productive. The switch from counting indexes to reslicing the
slice appears to improve performance in this case. The fairly arbitrary
value `na << 2` is like `nb / 4 > na` except that it computes faster,
and lets us avoid the expensive overhead unless we have reason to
expect that there's significantly more items in b than in a.

Improvements: Not huge in some cases, but sometimes quite noticeable,
especially as the frequency of overlap increases, which is also
the expensive case in other ways.

name                                              old time/op  new time/op  delta
ImportMutexSampleData/64K/2Kr/40/none/write-0-8    501ms ± 4%   486ms ± 2%     ~     (p=0.052 n=6+5)
ImportMutexSampleData/64K/2Kr/40/none/write-1-8    756ms ± 5%   698ms ± 5%   -7.62%  (p=0.002 n=6+6)
ImportMutexSampleData/64K/2Kr/80/none/write-0-8    292ms ± 3%   276ms ± 4%   -5.46%  (p=0.002 n=6+6)
ImportMutexSampleData/64K/2Kr/80/none/write-1-8    511ms ± 6%   482ms ± 4%   -5.72%  (p=0.015 n=6+6)
ImportMutexSampleData/64K/2Kr/240/none/write-0-8   153ms ± 3%   132ms ± 5%  -13.91%  (p=0.008 n=5+5)
ImportMutexSampleData/64K/2Kr/240/none/write-1-8   354ms ± 2%   215ms ± 6%  -39.41%  (p=0.004 n=5+6)
ImportMutexSampleData/1K/2Kr/40/none/write-0-8     565ms ± 3%   543ms ± 3%   -3.89%  (p=0.015 n=6+6)
ImportMutexSampleData/1K/2Kr/40/none/write-1-8     807ms ± 6%   778ms ± 3%     ~     (p=0.180 n=6+6)
ImportMutexSampleData/1K/2Kr/80/none/write-0-8     317ms ± 3%   300ms ± 1%   -5.40%  (p=0.002 n=6+6)
ImportMutexSampleData/1K/2Kr/80/none/write-1-8     462ms ± 3%   437ms ± 4%   -5.31%  (p=0.009 n=6+6)
ImportMutexSampleData/1K/2Kr/240/none/write-0-8    141ms ± 1%   119ms ± 2%  -15.85%  (p=0.004 n=5+6)
ImportMutexSampleData/1K/2Kr/240/none/write-1-8    213ms ± 3%   171ms ± 3%  -19.70%  (p=0.002 n=6+6)
2021-05-10 11:58:18 -05:00
Seebs
54f5cc799c performance hackery: add intersectCallback for use in running callbacks
In BitmapBitmapFilter.ConsiderData, we intersect things solely in order
to perform callbacks on them. Creating these intermediate arrays is
actually somewhat expensive, and all we're going to do with them is
make callbacks anyway.

So, we add a new `intersectCallback`, which behaves similarly to
`intersectionCount`, but which dramatically reduces the amount of memory
allocation associated with doing the callbacks; in some test cases
on mutex data, this code was >90% of all memory allocations, and
getting rid of that helps a lot.

At that point, we no longer need the separate intersectAny check,
because it doesn't save us any time anymore.
2021-05-10 11:58:18 -05:00
Seebs
ffb796448c make mutex tests smarter
The mutex tests had weird and un-idiomatic definitions for b.N, and
in particular would report ludicrously low times for high values of
b.N because they'd still only do a small amount of importing, then
get counted as having done a much larger number of iterations. Also,
the computation of the number of values to create was pretty noticably
wrong so the secondary data set was unduly tiny.

Do tests with ranked cache and larger row counts because we have
reason to suspect that the cache behavior is mattering. We adjust the
range of tests performed to reflect real world data a bit. We also
drop the "don't do large mutex tests" thing because the insanely
bad performance on larger mutex data should be fixed now, we hope.
2021-05-10 11:58:18 -05:00
Kuba Podgórski
252fadf6a0 Merge branch 'available-shards' of github.com:kuba--/molecula-pilosa into available-shards 2021-05-10 18:50:24 +02:00
Kuba Podgórski
6bdca67882 replace roaring.Bitmap by [][]byte 2021-05-10 18:45:23 +02:00
Nia
26b49cca21
fix remote available shard races (#3) 2021-05-10 18:36:40 +02:00
Maxton Huff
882327b0a6 remove inspect router 2021-05-10 10:36:24 -05:00
Kuba Podgórski
046b98bdf9
Merge branch 'master' into available-shards 2021-05-10 13:54:43 +02:00
Kuba Podgórski
b36de3146a write shards per node 2021-05-10 13:54:18 +02:00
Ben Johnson
03d258a3db
Merge pull request #1579 from molecula/backup-poc
[CORE-485] Backup CLI
2021-05-07 13:41:07 -06:00
Ben Johnson
e044a489fa
Merge branch 'master' into backup-poc 2021-05-07 13:09:54 -06:00
seebs
a302071b7f
Merge pull request #1587 from seebs/translateKeys
improve key creation/translation performance for large batches, especially on field keys
2021-05-07 14:09:36 -05:00
seebs
c473ff9925
Merge branch 'master' into translateKeys 2021-05-07 13:56:51 -05:00
tgruben
0fe0ae2b66
Merge branch 'master' into backup-poc 2021-05-07 13:37:11 -05:00
Ben Johnson
97cdc2405d
Merge pull request #1586 from molecula/rbf-rr-cache
Fix RBF root record cache build
2021-05-07 12:35:52 -06:00
Seebs
9e6ec3b17a break boltDB operations into chunks
boltDB's bucket.Put() is quadratic on "new keys put into a bucket during
this transaction", which is why BoltDB has warnings not to use it with over
100k new keys at a time. The translation store logic wasn't actually using
that. The actual value picked is smaller, based on some half-baked benchmarking.

We also avoid heap-allocating separate 16-byte (not 8-byte, of course,
because make(...) is *helping*) chunks twice for each key we insert, instead
allocating a single buffer which we reuse for each new transaction.

Also fixed a check against the nilness of the wrong pointer and generally
made CreateKeys and TranslateKeys a little more similar.
2021-05-07 13:19:15 -05:00
Ben Johnson
21c6203438 Fix linter 2021-05-07 11:15:13 -06:00
Ben Johnson
8a161bc423 Fix RBF root record cache build
This commit fixes an issue where the root record cache is only
built when a write transaction successfully commits. However, if
no write transactions are occurring then the the cache is never
built and saved so it is recomputed on every read tx.
2021-05-07 11:10:47 -06:00
Ben Johnson
7e804d7d08 Fix id alloc backup invocation 2021-05-07 10:59:01 -06:00
Ben Johnson
7284c4dd10 Add id alloc, col attrs, & row attrs backup 2021-05-07 10:59:01 -06:00
Todd Gruben
963bb3ec59 enable apiFieldTranslateData apiTranslateData 2021-05-07 10:59:01 -06:00
Ben Johnson
776b43a3cd Backup CLI 2021-05-07 10:59:01 -06:00
Kuba Podgórski
2517ee1bde remove unused 2021-05-07 15:45:30 +02:00
Kuba Podgórski
a79a36232f Write remote available shards to etcd, instead of local file. 2021-05-07 15:33:18 +02:00
Matthew Jaffee
1af85a818b
Merge pull request #1581 from jaffee/portmapper-npe
avoid nil pointer exception when failing to get listener
2021-05-05 14:18:22 -05:00
Matthew Jaffee
8274a8cfee avoid nil pointer exception when failing to get listener
instead of an opaque NPE on the next line, panic with explicit error
telling you what went wrong (in my case it was too many open files)
2021-05-04 15:17:41 -05:00
Alan Bernstein
7d1f9e33b8
Merge pull request #1577 from alanbernstein/core-478-query-history-nanoseconds
CORE-478 Add 'Nanoseconds' units to query-history 'runtime' json key
2021-04-22 20:23:28 -05:00
Alan Bernstein
7ffc103777 Add 'ns' units to query history runtime json 2021-04-22 15:26:15 -05:00
seebs
8c28a5f8ca
Merge pull request #1576 from seebs/ulimit
centralize attempts to set/check limits [CORE-426]
2021-04-21 15:05:23 -05:00
Seebs
1a5696fe23 centralize attempts to set/check limits
We check mmap limits, and try to set/increase our open file limits,
and we check the mmap limit when we start the server, and try to set
the open file limit every time we open a holder.

It's useless to do these things more than once, though. We migrate
these things to be run through a sync.Once, which runs all of them
the first time a server starts up, and then thereafter just returns
the error code from that first run. This should make test startup
ever so slightly cheaper, saving us potentially several microseconds,
but also reducing the spamminess of the message.

I've taken out the `sudo ulimit` advice since it's wrong, and the
documentation link is updated to point to our (now private!)
customer documentation.
2021-04-21 13:56:42 -05:00
seebs
0adc10d2c1
Merge pull request #1578 from seebs/bitmaaaapMaster
roaring ops log and TxBitmap fixes
2021-04-21 12:16:47 -05:00
Seebs
5a7c0971ca additional fragment tests: bitmap file growth, TxBitmap data loss
Checking issues encountered while tracking down an unexpected disk
usage increase.
2021-04-20 12:03:49 -05:00
Seebs
014a94c9c7 TxBitmap: track seen container keys
We can't assume that a container we've seen stays present in our bitmap
after possible remove operations. Solution: Track keys seen.
2021-04-20 12:03:44 -05:00
Seebs
5ffa4ba803 drop "batched" flag from Add operation
The "batched" flag creates a complexity which is that the return value of Add
might or might not be meaningful, but it doesn't really buy us very much.

If we are concerned about the ops log size of writing single ops as 21-byte
arrays of 1 op rather than as 13-byte ops, we can make the AddN code smarter
about how it writes ops. And probably should.

Along with this, change Remove to use the batched operation form, which
writes a more meaningful ops log, and return a meaningful value for changes
made. Otherwise, it ends up writing potentially thousands of ops to the
ops log without reporting any OpN, because the number of ops written isn't
the same as the number of changes those ops made. This could result in
files growing by megabytes without OpN changing.

There was a comment here about a test failing with RemoveN. I can't prove
it, but I strongly suspect that this was actually a result of that test
case hitting a particular bug that we eventually fixed, and which we might
have fixed sooner if we'd realized why using RemoveN made that test
fail.
2021-04-20 12:03:25 -05:00
Seebs
e93d2fe06c bitmap unmarshalling and testing bug fixes
When unmarshalling ops, we weren't adding a meaningful OpN to them,
resulting in misleading reports from `pilosa inspect`. Also, we were
mistakenly reporting things as "mapped" when they were actually
using their internal storage (as with small array containers).

Add the "sanity check" to `pilosa inspect` so that errors like the
above get noticed more easily and corrected. Also, to make that work,
have roaring.InspectBinary actually put containers in the bitmap
it creates rather than just creating info entries for them.
2021-04-20 12:01:21 -05:00
Seebs
ca216a14c5 fix bitmap.BitwiseEqual bugs
bitmap.BitwiseEqual had a couple of subtle bugs, and the net result
is that if the bitmap you were comparing to had an empty container after
the original bitmap ran out of containers, we'd spuriously report
the container as existing and being... the last container in the original,
actually.

Issues are both that we were grabbing the value from the wrong iterator,
and also that we were iterating twice per loop, and thus could also
have missed a non-empty container immediately following an empty one.
2021-04-20 12:01:13 -05:00
Kuba Podgórski
358e4b860e
Merge pull request #1574 from kuba--/public-name-validator
Make validateName function public,
2021-04-16 17:37:39 +02:00
Kuba Podgórski
74c1c8a86c
Merge branch 'master' into public-name-validator 2021-04-14 22:17:07 +02:00
Ben Johnson
3eca5944d4
Merge pull request #1571 from molecula/timestamp-epoch
Switch timestamp field to use epoch instead of min/max
2021-04-14 12:34:35 -06:00
tgruben
69e50b04d8
Merge pull request #1575 from tgruben/timestamp-client
Timestamp client
2021-04-14 12:58:33 -05:00
tgruben
813687d522
Merge branch 'timestamp-epoch' into timestamp-client 2021-04-14 11:37:40 -05:00
Todd Gruben
5737381d23 clientside timestamp support 2021-04-14 11:28:06 -05:00
Ben Johnson
bc4ad866c6
Merge branch 'master' into timestamp-epoch 2021-04-14 09:56:25 -06:00
seebs
8d1b1f24f9
Merge pull request #1551 from seebs/heartbeat
etcd: overhaul interactions to use heartbeats and cache things only until something changes.
2021-04-14 10:49:57 -05:00
Kuba Podgórski
29fe5cabaa
Merge branch 'master' into heartbeat 2021-04-14 17:10:20 +02:00
seebs
ee629bfd6a
Merge pull request #1569 from ajnavarro/improvement/reduce-executor-test-execution-time
[CORE-438] Reduce executor tests execution time from 2:30 to 30s reusing clusters.
2021-04-14 09:58:59 -05:00
Ben Johnson
ea01f7e37c Switch timestamp field to use epoch instead of min/max 2021-04-14 08:46:37 -06:00
Kuba Podgórski
ca1cbadb45 Make validateName function public, so other packages and projects (like IDK, Ingester) can re-use it 2021-04-14 13:33:26 +02:00
Antonio Navarro Perez
43c230039f Reduce executor tests execution time from 2:30 to 30s reusing clusters.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-04-14 11:30:02 +02:00
Seebs
7497d5fbe2 artificially increase heartbeat TTL for tests only
CI systems sometimes hiccup for five seconds, which causes heartbeat leases
to fail and breaks all sorts of things. As a workaround, update heartbeat
TTL for tests only. This might in turn cause different failures to do
with leader elections, but in theory those should be handled now?
2021-04-13 12:37:07 -05:00
Seebs
0638101d2a cluster state checking cleanups and fixes
A while back we started just polling the reported cluster state of one node
when starting a cluster for tests. This works fine if we're doing fresh
new etcd queries for every single operation -- but that's insanely
expensive, it turns out.

When we use the watcher, some nodes will report stale data for "a
while", where "a while" appears to be easily a couple dozen milliseconds.
This is probably irrelevant in most real-world cases, because the common
case (detecting a node going down) means that we have at least five
seconds after a node goes down before etcd notices the lease expiring,
and a few milliseconds more or less won't matter.

But we have tests that assume either that node 0 is always the
coordinator (wrong) or that waiting for node 0 to think the cluster
is up means that every node in the cluster thinks the cluster is up,
or at least that it means that the coordinator thinks the cluster is
up. We retried later operations but not the initial ones against
the coordinator.

In fact, we probably want to wait for the entire cluster to think
it's up before we start trying things on clusters.

We also replace the "CheckClusterState" function with the existing
AwaitState call, or a new AssertState which errors out since that's
the way we usually use AwaitState anyway.

In the AwaitPrimaryState function, which used to be
AwaitCoordinatorState in a different long-lost revision, we have
to delay until a primary node is available, or fail if one does
not become available, to avoid a panic. This probably shouldn't
happen anymore, because of the last change:

Also, rovide dummy topology.Node entries before metadata is read.

During initial startup, we want to be able to do things like determine
which node is the primary, even before we've read metadata from them.

To do this, we populate the node list with dummy entries that just have
the ID (the only part we need to sort our list), and a node state of
UNKNOWN.

This breaks the fancy logic for determining whether or not to update
the node data, because the initial status of UNKNOWN matches what we
get from SetMetadata giving us new data so we end up not realizing
that this was actually a meaningful change. But actually, that's
a pretty niche optimization; we usually only get state changes when
there's an actual change in state. The updates here are cheap
and only happen after a write (or on the first query) so it's not
worth making the logic a lot fancier to make it work, when we can
just do the simple thing and update any time the dirty flag is set.

We also standardize on a 50ms delay, because 1ms delays were
really expensive when each check was hitting etcd multiple times,
and 50ms is Usually Long Enough.
2021-04-13 12:37:07 -05:00
Seebs
d1752a7af7 switch to using a watcher to watch etcd changes
This is a significant overhaul! Quite a lot of things changed here.

Basically: Prior to this, every request for data from etcd implies
requesting the current live data from etcd, and then unpacking it or
extracting it in some way. This is expensive, which is why we have
a cache in front of it.

We don't need to do that! We can use a Watch, which notifies us
of changes as changes happen. However, there's some challenges and
difficulties along the way, and there's a couple of other changes
which are included here because it's a pain to try to separate them
out.

1. We require a logger to be provided to create our internal Etcd
wrapper. We then use that logger, instead of `fmt.Printf`. This makes
debugging messages work better, and also diagnostics, and so on.

2. The internal client that we are reusing can enter a failed state
after a leader election, in which case we have to recreate the client
to have a working client. We add a new internal-use method,
`retryClient`, which wraps a function which takes an etcd client
and returns an error, and checks for leader-election type errors
and retries creating the client when they happen. That last bit
has not been successfully tested because it's actually really hard
to trigger this now. (Because it was related in part to the
amount of etcd traffic we were producing, which is reduced.)

3. The general swap over from looking things up to unpacking things
as they come in, then returning those already-unpacked things when
we get requests.

With this change, *many tests will fail*. That is addressed by
a separate commit which addresses the secondary problem, which is
that some of our test harness code was relying on the assumption
that if any node in a cluster thinks the cluster is up, every node
will. That was usually true when we were doing everything as
expensive fully-synchronized cluster checks, but becomes significantly
less reliably true in real-world cases where nodes are also
going down sometimes, or nodes are going up and down unexpectedly.
2021-04-13 12:37:07 -05:00
Seebs
fd8a19278c add TestMain wrapper in ctl
The TestMain wrapper gets us the fancy testhook stuff tracking whether we're
deallocating things as expected, and we probably want that.
2021-04-13 12:37:07 -05:00
Seebs
6b1cd1e43b drop etcd-with-cache option
The new etcd implementation has internal caching-like behavior which is
much more reliable (it doesn't use a TTL, it just updates when there's updates
to process) so we don't need this cache.
2021-04-13 12:37:07 -05:00
Ben Johnson
6616b0d6f0
Merge pull request #1570 from molecula/extract-timestamp
Fix timestamp Extract()
2021-04-13 11:18:19 -06:00
Ben Johnson
7863a97add
Merge branch 'master' into extract-timestamp 2021-04-13 10:36:31 -06:00
Alan Bernstein
a0992e0393
Merge pull request #1573 from alanbernstein/logger-prefixes-again
CORE-72 Add log prefix levels
2021-04-12 22:57:42 -05:00
Alan Bernstein
ce4ed1d81d Apply review suggestion
typo fix

Co-authored-by: Travis Turner <travis@pilosa.com>
2021-04-12 22:25:26 -05:00
Alan Bernstein
54ff05c266 Apply review suggestion
typo fix

Co-authored-by: Travis Turner <travis@pilosa.com>
2021-04-12 22:25:26 -05:00
Alan Bernstein
177c27dc31 Switch to new logger in client code (go-pilosa) 2021-04-12 22:25:13 -05:00
Alan Bernstein
285d0a0af8 Add log prefix levels 2021-04-12 20:33:39 -05:00
tgruben
ebbb196a23
Merge pull request #1560 from tgruben/delete
[CORE-245] added pql delete function
2021-04-12 16:47:40 -05:00
tgruben
83eb82f271
Merge pull request #5 from seebs/delete
Delete hackery
2021-04-12 16:22:26 -05:00
Seebs
2833365aae reuse the findExisting filter between fields, drop separate hack for existence
The existence field wasn't working because runs were broken for filters in
RBF. Fixing that allows us to simplify the logic. Also, we reuse the
findExisting filter because the filter's cached collection of containers
can be reused between things, allowing us to reduce allocations when
there's a lot of views.
2021-04-12 16:14:45 -05:00
Seebs
269837414e rbf/intoContainer: ensure correct N, avoid recounting
The remake container logic (used to avoid allocating extra containers while
applying filters) relied on roaring recomputing N, which it did for bitmaps
but didn't do for runs. Fix this both ways; it would now do that for runs,
but also we add "with explicit N" variants and use those since we have a
correct count already, and don't need it. This means fewer popcounts on
bitmaps, and working at all on runs.
2021-04-12 16:13:16 -05:00
Ben Johnson
2864a851ab Fix timestamp Extract() 2021-04-12 13:58:46 -06:00
Ben Johnson
0b76fd5179 Switch timestamp field to use epoch instead of min/max 2021-04-12 13:55:54 -06:00
tgruben
84c269bfc0
Update delete_test.go 2021-04-12 13:38:58 -05:00
tgruben
2d85918f43
Merge branch 'master' into delete 2021-04-09 14:31:40 -05:00
Samir Patel
da749cc757
Merge pull request #1563 from 54mir/timestamp-in-orm
Replicate timefield functionality in pilosaclient
2021-04-09 13:36:39 -05:00
tgruben
b6c80969a1
Merge branch 'master' into timestamp-in-orm 2021-04-09 12:51:36 -05:00
tgruben
f6632bcaca
Merge branch 'master' into delete 2021-04-09 12:51:03 -05:00
Ben Johnson
eb119d2d35
Merge pull request #1568 from molecula/fix-int-fk
Remove integer fk error check
2021-04-09 11:50:41 -06:00
tgruben
3bc4309a96
Merge branch 'master' into delete 2021-04-09 12:41:31 -05:00
tgruben
12748d75d3
Merge branch 'master' into timestamp-in-orm 2021-04-09 12:41:12 -05:00
Ben Johnson
fbd713d435
Merge branch 'master' into fix-int-fk 2021-04-09 11:28:07 -06:00
Ben Johnson
84f9fde25a
Merge pull request #1567 from molecula/import-timestamp-values
Fix timestamp value import
2021-04-09 11:28:01 -06:00
Ben Johnson
e1909661d5 Remove integer fk error check 2021-04-09 11:01:28 -06:00
Ben Johnson
5defbe3ef2 Fix timestamp value import 2021-04-09 10:56:25 -06:00
tgruben
a60c70b2a5
Merge branch 'master' into delete 2021-04-09 10:26:30 -05:00
tgruben
4b484f41f2
Merge branch 'master' into timestamp-in-orm 2021-04-09 10:20:46 -05:00
Ben Johnson
8802856120
Merge pull request #1564 from molecula/timestamp-fixes
Fix timestamp field issues
2021-04-09 09:01:30 -06:00
Ben Johnson
485c1c888b
Merge branch 'master' into timestamp-fixes 2021-04-09 08:31:55 -06:00
Nia
95dd262bb3
Merge pull request #1559 from niaow/id-alloc-desync-structured-error
[CORE-386] Change ID allocation to return a structured error on offset desync
2021-04-09 10:28:26 -04:00
Ben Johnson
d70eb737cb Fix timestamp field issues 2021-04-09 08:26:12 -06:00
Nia
6140fc9d4c
Merge branch 'master' into id-alloc-desync-structured-error 2021-04-09 09:16:25 -04:00
Todd Gruben
ac7a8c3dd5 validate existence 2021-04-09 07:24:43 -05:00
Kuba Podgórski
6caae41432
Merge pull request #1565 from kuba--/fix-panic
Fix panic on field not found on /import
2021-04-09 14:01:07 +02:00
Kuba Podgórski
c021b873d5 Fix panic on field not found on /import 2021-04-09 13:38:39 +02:00
Samir Patel
b1d1ac0cae
Merge branch 'master' into timestamp-in-orm 2021-04-08 13:40:14 -05:00
Samir
83932041a5 Replicate timefield functionality in pilosaclient 2021-04-08 13:21:49 -05:00
tgruben
784c78e313
Merge branch 'master' into delete 2021-04-08 10:05:31 -05:00
Nia
dbf9b14963
Merge pull request #1562 from niaow/update-before-install
Update the package database before installing dependencies in CI
2021-04-08 10:46:47 -04:00
Todd Gruben
dcd6c649e8 skip blue-green on delete test 2021-04-08 09:37:34 -05:00
Nia Weiss
c127f0a959
update the package database before installing dependencies in CI 2021-04-08 10:20:16 -04:00
Todd Gruben
918644820b added pql delete function 2021-04-07 13:57:43 -05:00
Ben Johnson
7e369aeac4
Merge pull request #1558 from molecula/timestamp
CORE-372: Add timestamp field type support
2021-04-06 11:28:10 -06:00
Ben Johnson
cfc725e799 Add timestamp field type support 2021-04-06 10:50:10 -06:00
Alan Bernstein
f75e46c2f6
Merge pull request #1544 from alanbernstein/clarify-longquerytime-log
Add some context to the longquerytime log message
2021-04-06 11:18:07 -05:00
Nia Weiss
7734bcd53c
change ID allocation to return a structured error on offset desync
This is used to handle a possible case where a kafka partition is moved to another ingester while a previous ingester is still processing it, causing 2 ingesters to process it at the same time.
This allows a duplicate ingester to skip past messages which have already been ingested.
2021-04-06 10:39:22 -04:00
Alan Bernstein
2e93b2eea2 Add some context the longquerytime log message 2021-04-05 17:02:58 -05:00
Antonio Navarro Perez
6664e86222
Merge pull request #1556 from ajnavarro/tests/review-skipped-tests 2021-03-31 16:29:02 +02:00
Kuba Podgórski
ddf7ff7b70
Merge branch 'master' into tests/review-skipped-tests 2021-03-31 15:38:36 +02:00
Nia
aa212cb83b
Merge pull request #1547 from niaow/external-lookup
[CORE-388] Add ExternalLookup query
2021-03-31 08:35:54 -04:00
Nia
d5da6e229c
Merge branch 'master' into external-lookup 2021-03-31 08:12:18 -04:00
Antonio Navarro Perez
ebe3afcb96
Merge branch 'master' into tests/review-skipped-tests 2021-03-31 14:03:35 +02:00
Matthew Jaffee
4856c68760
Merge pull request #1542 from Maxtonian/percentile
CORE-412 change percentile value ranges from 0-1 to 0-100
2021-03-30 09:23:12 -05:00
Maxton Huff
ff82447647
Merge branch 'master' into percentile 2021-03-30 08:20:45 -05:00
Maxton Huff
8c20d9a51c remove redundant error message 2021-03-30 08:13:36 -05:00
Antonio Navarro Perez
03659d8d39 Review skipped tests, and try to execute them again.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-30 13:37:33 +02:00
Nia
71b2cb80f7
Merge pull request #1555 from niaow/test-tx-commit-rollback-single-writer-race
Fix DB-close race condition in TestTx_CommitRollback/SingleWriter
2021-03-29 18:13:37 -04:00
Maxton Huff
13ec97abf5 add new test cases for limits and clarify error messages 2021-03-29 16:55:50 -05:00
Nia
1fa3947f8d
Merge branch 'master' into test-tx-commit-rollback-single-writer-race 2021-03-29 17:51:54 -04:00
Maxton Huff
4c8dc8d54f address variable declaration warning 2021-03-29 16:24:56 -05:00
Maxton Huff
377c3f3654 rework checks and reword incorrect type error message 2021-03-29 15:59:30 -05:00
Nia Weiss
c931a3e63f
fix DB-close race condition in TestTx_CommitRollback/SingleWriter
Due to lack of synchronization, this test would sometimes close the DB before terminating a transaction:
=== RUN   TestTx_CommitRollback/SingleWriter
    tx_test.go:132: db still has 1 active transactions; must closed before closing db

The test now waits for the goroutines to terminate before closing the DB.
2021-03-29 15:06:07 -04:00
Kuba Podgórski
6185abacc1
Merge pull request #1552 from kuba--/test-pilosa/client
[CORE-458] Integration tests client against cluster
2021-03-29 19:07:53 +02:00
Nia Weiss
9bc1b23b7e
change "External" DB to "Lookup" DB 2021-03-29 12:54:29 -04:00
Kuba Podgórski
c23bc901e8 Integration tests client against cluster 2021-03-29 18:31:45 +02:00
Kuba Podgórski
b835221ded
Merge pull request #1553 from kuba--/wth-is-vprint
[CORE-452] Move `vprint` to separate package
2021-03-29 18:10:18 +02:00
Kuba Podgórski
9a02004a4f Move vprint to separate pakage 2021-03-29 14:29:19 +02:00
Nia Weiss
c4aad290ed
address ExternalLookup review comments 2021-03-29 08:22:41 -04:00
Kuba Podgórski
8948c4531a
Merge pull request #1550 from ajnavarro/fix/use-at-least-3-nodes-on-cluster-tests
[CORE-432] Add at least 3 nodes on test clusters.
2021-03-27 17:07:17 +01:00
Maxton Huff
4ce71eeddf change nth value limit message and number of test int64 nth values 2021-03-26 16:54:44 -05:00
Maxton Huff
f06c13abcd alter incorrect type error message 2021-03-26 16:11:16 -05:00
Maxton Huff
6c94bfdb5e improve error responses and change switch statement to allow int64 2021-03-26 13:56:22 -05:00
Maxton Huff
87412068f1 add new test to account for int64 nth values 2021-03-26 13:01:31 -05:00
Antonio Navarro Perez
79c6493d9a Fix executor test.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-26 13:21:56 +01:00
Antonio Navarro Perez
0483553b16 Fix two more tests
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-26 13:04:15 +01:00
Antonio Navarro Perez
7ec85a1c0f Add at least 3 nodes on test clusters.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-26 10:16:41 +01:00
Maxton Huff
8746444cdb add error message for invalid type 2021-03-25 16:57:08 -05:00
Maxton Huff
61beef7e5a add Int64() function and include case of int64 2021-03-25 16:27:55 -05:00
Kuba Podgórski
878f7fd4e7
Merge pull request #1546 from kuba--/fix-pb-endpoints
Update internal endpoints
2021-03-25 18:25:38 +01:00
Nia Weiss
e9b92e1cd4
add ExternalLookup query 2021-03-25 13:21:28 -04:00
Kuba Podgórski
65cb2cdf73 Update internal endpoints 2021-03-25 18:00:56 +01:00
Kuba Podgórski
0649ba3f8d
Merge pull request #1545 from kuba--/fix-endpoint
Fix internal endpoint
2021-03-25 17:18:37 +01:00
Kuba Podgórski
761190ec32 Fix internal endpoint 2021-03-25 16:44:05 +01:00
Kuba Podgórski
989a01db33
Merge pull request #1539 from kuba--/core-230/go-pilosa
[CORE-230] Combine go-pilosa and pilosa into one repo
2021-03-25 15:31:32 +01:00
Kuba Podgórski
40337cff09
Merge branch 'master' into core-230/go-pilosa 2021-03-24 21:23:04 +01:00
tgruben
76b676a256
Merge pull request #1537 from tgruben/tds
[CORE-311] etcd tls configuration support
2021-03-24 12:30:50 -05:00
Kuba Podgórski
000f708c40 Address PR comments
+ some docs
2021-03-24 18:09:01 +01:00
Maxton Huff
d3438e8a80 correct k calculation and change test nth values 2021-03-24 10:58:47 -05:00
Kuba Podgórski
d6129517db
Update handler.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2021-03-24 16:49:32 +01:00
Todd Gruben
e46a41638f Merge branch 'tds' of github.com:tgruben/privilosa into tds 2021-03-24 10:44:31 -05:00
Todd Gruben
6bafa989e0 adjust etcd config comments 2021-03-24 10:43:28 -05:00
tgruben
160e64fbf3
Merge branch 'master' into tds 2021-03-24 10:07:50 -05:00
Kuba Podgórski
913c909ef7
Merge branch 'master' into core-230/go-pilosa 2021-03-24 15:19:44 +01:00
Kuba Podgórski
03386392ea Fix typos, replace panics by error 2021-03-24 15:15:50 +01:00
Antonio Navarro Perez
7cf4233fdb
Merge pull request #1541 from ajnavarro/fix/call-cancel-if-any 2021-03-24 11:35:41 +01:00
Antonio Navarro Perez
ffcaa1b500
Merge branch 'master' into fix/call-cancel-if-any 2021-03-24 10:30:39 +01:00
Maxton Huff
40e3acc3e4 change percentile value ranges from 0-1 to 0-100 2021-03-23 16:57:37 -05:00
tgruben
9e6855b315
Merge branch 'master' into tds 2021-03-23 16:40:48 -05:00
Ben Johnson
1228c6e188
Merge pull request #1532 from molecula/fix-delete-field-panic
CORE-334: Fix panic on field deletion
2021-03-23 09:03:46 -06:00
Antonio Navarro Perez
6e6eb962ee Call cancel when we try to renew the lease after an error.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-23 14:20:14 +01:00
Todd Gruben
8c4d7e09ff re-use pilosa tls settings 2021-03-22 16:48:09 -05:00
Kuba Podgórski
1e5388dbe9 Move internals proto files into separate package (pb) 2021-03-22 20:28:00 +01:00
Kuba Podgórski
8131e807bf Add client package with go-pilosa implementation 2021-03-22 20:22:38 +01:00
Ben Johnson
5d2f957404
Merge branch 'master' into fix-delete-field-panic 2021-03-22 08:32:34 -06:00
Todd Gruben
f52b88a962 etcd tls configuration support 2021-03-22 09:10:32 -05:00
Nia
b6810f3ce7
Merge pull request #1535 from niaow/fix-unkeyed-panic
CORE-382 Handle translation errors when using keys against an unkeyed index
2021-03-17 17:16:55 -04:00
Nia Weiss
6f421dad69
handle translation errors when using keys against an unkeyed index
This also adds tests for our error outputs.
2021-03-17 12:02:29 -04:00
Kuba Podgórski
16245b1742
Merge pull request #1534 from kuba--/call-agg/335
CORE-335 Consistency with aggregate functions
2021-03-16 19:54:12 +01:00
Kuba Podgórski
d370452449 Add helper function FirstStringArg 2021-03-16 16:32:35 +01:00
Kuba Podgórski
1dac4c7622 Consistency with aggregate functions 2021-03-16 15:02:40 +01:00
Ben Johnson
195050e20c CORE-334: Fix panic on field deletion 2021-03-15 12:19:43 -06:00
Matthew Jaffee
c6ea56bbad
Merge pull request #1529 from travisturner/cache-bitdepth
[Core-370] Cache BitDepth on bsiGroup during index.Open
2021-03-15 07:38:05 -05:00
Travis
314cf3461d
Cache BitDepth on bsiGroup during index.Open.
Before this change, we were only caching the BitDepth on the
field.options. This was ok as long as applyOptions() was called after
that. But unfortunately, during startup, applyOptions() was called prior
to that being set. So with this commit, we explicitly set the value in
bsiGroup.BitDepth as well.
2021-03-14 22:51:24 -05:00
Matthew Jaffee
9b3cce619a
Merge pull request #1530 from jaffee/revert-custom-json
Revert "Basic pilosa changes for oracle support"
2021-03-14 22:50:37 -05:00
Matt Jaffee
11288c2ae8
Revert "Basic pilosa changes for oracle support"
This reverts commit 47e74f2603.
2021-03-14 22:17:26 -05:00
Nia
c694189648
Merge pull request #1523 from niaow/idalloc-fix
CORE-361 Fix ID allocation API after disco
2021-03-14 16:52:52 -04:00
Nia Weiss
2f4a2bf98f
fix ID allocation API after disco
The ID allocation API was broken because the operations were removed from the list allowed in the NORMAL cluster state.
Additionally the operations were set to only run on non-primaries (where they were actually only supposed to run on the primary).
2021-03-13 07:41:00 -06:00
Nia
ec899bcc64
Merge pull request #1519 from niaow/rbf-typos
fix a typo in the RBF spec
2021-03-13 00:25:12 -05:00
Ben Johnson
ddb8c95737
Merge branch 'master' into rbf-typos 2021-03-12 20:16:17 -07:00
tgruben
29b8501aff
Merge pull request #1527 from tgruben/core-334-fix
[CORE-334]  more graceful error handling for corrupt containers
2021-03-12 15:16:12 -06:00
Todd Gruben
346a248019 Merge branch 'core-334-fix' of github.com:tgruben/privilosa into core-334-fix 2021-03-12 13:28:11 -06:00
Todd Gruben
2711bf321f replace error with wrap 2021-03-12 13:27:28 -06:00
tgruben
fd7ea42451
Merge branch 'master' into core-334-fix 2021-03-12 12:11:52 -06:00
Kuba Podgórski
38c2c4ad6f
Merge pull request #1526 from seebs/testLeaks
CORE-358 Test leaks
2021-03-12 19:10:02 +01:00
Todd Gruben
94d7b295ea added more graceful error handling for corrupt containers 2021-03-12 10:37:40 -06:00
seebs
78ed9a2d57
Merge branch 'master' into testLeaks 2021-03-12 10:02:11 -06:00
Kuba Podgórski
1b486ac812
Merge pull request #1522 from kuba--/core-344
CORE-344: Fix deprecation plan for "github.com/golang/protobuf/protoc-gen-go/generator" package
2021-03-12 15:29:54 +01:00
Kuba Podgórski
61585b251e
Merge branch 'master' into testLeaks 2021-03-12 14:14:03 +01:00
Kuba Podgórski
4043f22db2
Merge branch 'master' into core-344 2021-03-12 14:08:03 +01:00
Travis Turner
81c47b778e
Merge pull request #1525 from travisturner/startup-log-dir
[CORE-362] Create the data directory during "log startup" if it doesn't already exist
2021-03-12 06:47:45 -06:00
Kuba Podgórski
1ba52dbca9 Update go.sum 2021-03-12 13:06:23 +01:00
Kuba Podgórski
a12a130420
Merge branch 'master' into core-344 2021-03-12 12:51:58 +01:00
Kuba Podgórski
ddc924de0c go mod tidy 2021-03-12 12:48:53 +01:00
Seebs
ef8dd91077 report errors more clearly when trying to recreate leases
There's some loose ends here because really we probably want to be
using the top-level server logger, and we should fix that, but in the
mean time, let's not swallow the errors as much, because the last
line printed doesn't actually show what the error was, but it could.

To do this, we distinguish between the current error (which might
be a wrapper around DeadlineExceeded) and a previous error which
we might prefer to return, if one exists, since it's more likely
the "real" cause.
2021-03-11 19:42:10 -06:00
Seebs
1045268f01 use testhook to ensure temporary files and directories are cleaned up
In nearly all cases, we can just switch ioutil.TempDir->testhook.TempDir
and similarly for TempFile. There's one case where we can't because we
need files to be removed before tests are over.

Also in the process give identifiable names to a lot of temporary files
and make sure they're being cleaned up, and don't use "/tmp/foo" as a
file name in a test that could be running in more than one test process
at once. :)
2021-03-11 19:42:10 -06:00
Travis
9e0ea9709a
Create the data directory during "log startup" if it doesn't already exist.
Prior to using etcd for node membership, the data director was created
during the cluster topology setup. Since that no longer exists, we
weren't actually creating the data directory before getting to
logStartup(). So this change ensure that the data directory exists.
2021-03-11 17:31:46 -06:00
tgruben
9b913ce904
Merge pull request #1489 from tgruben/theoracle
Theoracle
2021-03-11 16:11:38 -06:00
tgruben
391588bd1b
Merge branch 'master' into theoracle 2021-03-11 13:56:34 -06:00
Alan Bernstein
7df5375572
Merge pull request #1524 from alanbernstein/fix-null-schema
Represent zero indexes in /schema response as [] instead of null
2021-03-11 13:23:19 -06:00
tgruben
21910ef321
Update main.go 2021-03-11 11:47:57 -06:00
tgruben
a5dceaae11
Update main.go 2021-03-11 11:26:58 -06:00
Alan Bernstein
8e123b821d Replace null with [] in schema response 2021-03-11 11:23:20 -06:00
Todd Gruben
47e74f2603 Basic pilosa changes for oracle support 2021-03-11 11:16:53 -06:00
Kuba Podgórski
95eaab8ffc
Merge pull request #1514 from seebs/discoSyncer
CORE-299 check for nil translate store while reading translate entries
2021-03-11 13:03:24 +01:00
Nia Weiss
e73d9cb61b
fix a typo in the RBF spec 2021-03-10 14:25:38 -05:00
Kuba Podgórski
3fde2dcac2
Merge branch 'master' into discoSyncer 2021-03-10 12:35:10 +01:00
Kuba Podgórski
5af850c64a
Merge pull request #1518 from kuba--/fix-metadata-noder
Get metadata in Tx. Fix Nodes implementation
2021-03-10 11:24:09 +01:00
Kuba Podgórski
4c787870b2 Get metadata in Tx. Fix Nodes implementation 2021-03-10 00:28:49 +01:00
Seebs
810f840839 combine field and index translation readers
There's no need to have two different translation readers, a single
reader can handle both partitions and fields at the same time, so we
can combine them. This may not actually change things much but was
a useful step in diagnosing a different problem with translate readers,
and I think it is a minor improvement so I'm preserving the patch
just in case.
2021-03-09 13:37:51 -06:00
Seebs
76e4181740 don't reuse sync.Mutex between translate readers
The functional option and returned closure combine to result in
us using the same sync.Mutex object for every TranslateReader on
a given server, which means that if one of them isn't producing anything,
we eventually end up waiting on that with all the others blocked
waiting for the lock. Use separate locks for each, of the same
type as the one initially provided as a template. This does mean
that multiple readers can be operating at once, but in theory
no two readers should ever be writing to the same stores, we
think.
2021-03-08 17:04:52 -06:00
Seebs
51744dc77a check for nil translate store while reading translate entries
If we are using replication, we can be a replica translate store for a
partition, which means we start a translate store reader to replicate
data for it. The translation logic does not admit *stopping* the
translate reader, only "resetting" it (stopping and immediately
restarting), so the translate reader just runs until it hits an error
and terminates, which it does even if perhaps it shouldn't. Oops.

Anyway, one potential failure mode is that if you hit timing just
right, you can end up trying to process translation *while* the
index is being closed, and the index can close its translation stores,
and make them all nil, right before we request a store and try to use
it. Another is a similar error, but during the initial startup of the
translate store readers. Either way, we want to error out of the
process cleanly if this happens.

This could also happen during initial creation, perhaps.

We're aborting translation sync on these errors, because otherwise
we'd continue accepting new keys, and then end up with our highest
known key being higher than some keys we missed; this way the next
restart will restart from the last key we have.
2021-03-08 17:04:52 -06:00
Travis Turner
45577494c3
Merge pull request #1517 from travisturner/datadir-take-3
Remove stutter and suffix from backend files
2021-03-08 11:50:42 -06:00
Travis Turner
2a0765d7f0
Merge branch 'master' into datadir-take-3 2021-03-08 11:21:05 -06:00
Kuba Podgórski
d6e9e88872
Merge pull request #1516 from kuba--/test-close
Close resources in TestLeasedKv
2021-03-08 11:01:40 +01:00
Travis
f78a6508f0
Remove stutter and suffix from backend files 2021-03-07 22:11:51 -06:00
Kuba Podgórski
7b005f69c6 Close resources in TestLeasedKv 2021-03-06 12:03:57 +01:00
Travis Turner
ab50403c35
Merge pull request #1512 from travisturner/datadir-take-2
Core-316 Reorganize Pilosa datadir
2021-03-05 17:15:03 -06:00
Travis
cad78f1d34
remove "Default*" from const names 2021-03-05 16:56:44 -06:00
Travis
5191d0c3f4
remove unnecessary skip check 2021-03-05 16:56:44 -06:00
Travis
4661f3ac08
reorganize the storage backends directory 2021-03-05 16:56:44 -06:00
Travis
4738a818d2
change attributes file ".data" to "column/row-attributes" 2021-03-05 16:56:44 -06:00
Travis
345d076fdf
introduce "fields" directory between index and field 2021-03-05 16:56:44 -06:00
Travis
4e7ec34c6d
change directory ".disco" to "disco" 2021-03-05 16:56:44 -06:00
Travis
7789e24965
introduce "indexes" directory between datadir and index 2021-03-05 16:56:43 -06:00
Matthew Jaffee
863e57d5d1
Merge pull request #1513 from ajnavarro/disco/improve-leased-keys
[CORE-312] Improve leased keys.
2021-03-05 16:47:54 -06:00
Antonio Navarro Perez
542a98548a Breaking code at friday afternoon...
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
2927943734 Copy paste fix.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
feea0fa347 Requested changes.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
85a43c519d Fix problem with context errors.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
df0064c55f Add godoc.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
955ab2b5a0 Requested changes
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
851c41cd45 Implement infinite lease renewal logic.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Antonio Navarro Perez
7a1e4cd2d7 Improve leased keys.
Added a leasedKV struct in charge of maintain a lease for a specific
key.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-05 23:35:53 +01:00
Matthew Jaffee
6966c3f7c3
Merge pull request #1515 from jaffee/invalid-pilosa-message-fix
CORE-319 Fix issue where restarting a node fails to sync and logs "invalid pilosa.Message"
2021-03-05 15:58:06 -06:00
Matt Jaffee
f97ac4928c
add test for pilosa.Message issue
this doesn't quite work as-is, but I verified that it reproduced/fixed
the issue by adding a panic where the problem log statement
is. There's a follow up ticket to fix the test... it's just a bit open
ended as to the best way to do that.
2021-03-05 14:16:52 -06:00
Matt Jaffee
08d4511e6c
fix issue where restarting a cluster logged "invalid pilosa.Message"
we were sending pilosa.Message objects from a spool, but actually
passing a pointer to them rather than the Message itself. I'm
concerned this wasn't caught in any test, and also curious if that
needed to be a pointer for some reason or if it's a typo.

Definitely need to write a test still.
2021-03-05 12:51:39 -06:00
Travis Turner
fa9e17878f
Merge pull request #1503 from molecula/disco
DisCo
2021-03-04 17:24:42 -06:00
Matt Jaffee
bb713f94a5
Merge branch 'master' into disco 2021-03-04 16:56:35 -06:00
Cody Soyland
bf050a69d2
Merge pull request #1511 from codysoyland/release-on-tag
Run release stage when tags are pushed
2021-03-04 15:22:01 -06:00
Cody Soyland
ba8fb56a4a
Run release stage when tags are pushed 2021-03-04 15:11:57 -06:00
Matthew Jaffee
911c874fa1
Merge pull request #1510 from jaffee/upgrade-lettuce
upgrade UI for final Molecula 3.x/Pilosa 2.x release
2021-03-04 15:05:08 -06:00
Matt Jaffee
e1f2ffe614
upgrade UI for final Molecula 3.x/Pilosa 2.x release 2021-03-04 14:44:38 -06:00
Travis Turner
10a55040e8
Merge pull request #1509 from travisturner/disco-remove-gossip-config
Remove gossip config
2021-03-04 14:19:35 -06:00
Travis
42d69d6c5d
Remove gossip config 2021-03-04 13:51:18 -06:00
Nia
d2b0749c8a
Merge pull request #1507 from niaow/always-build-release
CORE-313 Build release bundles on every merge
2021-03-04 13:29:46 -05:00
Nia Weiss
0fbdbc7ccb
build release bundles on every merge 2021-03-04 12:34:51 -05:00
Kuba Podgórski
da3116a642
Merge pull request #1504 from kuba--/txn-state
Always Put states in Txn
2021-03-04 00:21:40 +01:00
Kuba Podgórski
d311b0cac4 Comment Status function
+ make waitForStatus more generic
2021-03-03 23:47:47 +01:00
Kuba Podgórski
fa293ba6c3 Address PR comments 2021-03-03 16:13:03 +01:00
Kuba Podgórski
a14baf8c15 waitForStatus for cluster test 2021-03-03 14:22:44 +01:00
Kuba Podgórski
6f7d748c8a Always Put states in Txn 2021-03-03 13:37:20 +01:00
Travis
883e687094
fix missing bracket 2021-03-02 22:14:07 -06:00
Travis
ea8b07d380
Merge branch 'master' into disco 2021-03-02 22:11:04 -06:00
Matthew Jaffee
c4c4a49f13
Merge pull request #1483 from jaffee/core-101-disco
CORE-101 Percentiles on disco
2021-03-02 22:02:27 -06:00
Matt Jaffee
f81c0cab6b
move 0.0 check up to right after Min is queried 2021-03-02 21:59:46 -06:00
Matt Jaffee
1e4cc12bd0
handle 0th percentile properly 2021-03-02 21:47:27 -06:00
Matt Jaffee
b1f9e6ad05
turn off parallel for variousQueries 2021-03-02 20:36:54 -06:00
Matt Jaffee
ad88f4fac8
refactor tests to reuse clusters more 2021-03-02 20:36:54 -06:00
Matt Jaffee
88b093db7a
add 60m timeout to topt-race tests to match topt 2021-03-02 20:36:53 -06:00
nagamocha3000
7da218727d
Separate out tests on Percentile to top level 2021-03-02 20:36:53 -06:00
nagamocha3000
832c6f1a71
Restore filter argument 2021-03-02 20:36:53 -06:00
nagamocha3000
66d12f88e2
Remove filter to check if it's cause of leaks 2021-03-02 20:36:53 -06:00
nagamocha3000
abe8e61539
Remove check for basic response 2021-03-02 20:36:53 -06:00
nagamocha3000
4e81fd8101
Limit size of nums to 100 2021-03-02 20:36:53 -06:00
nagamocha3000
4be9ac7554
Remove percentile tests temporarily to see if they are the cause 2021-03-02 20:36:53 -06:00
nagamocha3000
1947325e00
Fix error on index name for Percentile query 2021-03-02 20:36:53 -06:00
nagamocha3000
2de543bc55
Rename index to avoid possible conflict 2021-03-02 20:36:52 -06:00
nagamocha3000
a6c157d5db
Fix errenous estimation that caused infinite loop 2021-03-02 20:36:52 -06:00
nagamocha3000
ef58b66e2c
Add ability to compose filter Row Call with Percentile 2021-03-02 20:36:52 -06:00
nagamocha3000
131d4fd97c
Make tests for median more extensive 2021-03-02 20:36:52 -06:00
nagamocha3000
72af5f37df
Remove redundant assignment to countCall.children since we already have the reference 2021-03-02 20:36:52 -06:00
nagamocha3000
3fb79b4d97
Fix errors on creating pql Call 2021-03-02 20:36:52 -06:00
nagamocha3000
d740a0cda7
Add execution for median 2021-03-02 20:36:52 -06:00
nagamocha3000
26fd199716
Add basic test for Percentile query 2021-03-02 20:36:51 -06:00
nagamocha3000
30a7e0f0da
Add pql syntax for Percentile 2021-03-02 20:36:51 -06:00
Matthew Jaffee
61e84a01dc
Merge pull request #1500 from jaffee/default-rbf
change default backend to RBF, remove separate RBF race target
2021-03-02 20:34:32 -06:00
Matt Jaffee
52a0c90cd6
change default backend to RBF, remove separate RBF race target 2021-03-02 17:50:56 -06:00
Matthew Jaffee
34e742d9c6
Merge pull request #1502 from niaow/fix-more-kv
fix more incorrect uses of KV
2021-03-02 17:50:29 -06:00
Nia Weiss
a698eeaac2
fix more incorrect uses of KV 2021-03-02 18:35:19 -05:00
Matthew Jaffee
b790d2cc5f
Merge pull request #1501 from travisturner/disco-bitdepth-test-fix
fix SaveMeta test; ensure storage backend env is used
2021-03-02 17:26:52 -06:00
Travis
3d10af9d47
fix SaveMeta test; ensure storage backend env is used 2021-03-02 17:19:45 -06:00
Cody Soyland
acc1175c93
Merge pull request #1498 from codysoyland/docker-ci-version
Workaround CI versioning issue
2021-03-02 15:03:52 -06:00
Cody Soyland
0532987d57
Workaround CI versioning issue 2021-03-02 14:39:32 -06:00
Maxton Huff
068325277d
Merge pull request #1465 from Maxtonian/topNfieldequal
Allow "field=" for TopN()
2021-03-02 14:32:25 -06:00
Matthew Jaffee
0568daaa14
Merge pull request #1486 from ajnavarro/disco/remove-unused-code-and-godoc
[DISCO] Add documentation and try to remove code.
2021-03-02 14:07:06 -06:00
Maxton Huff
d61fdc2521
Merge branch 'master' into topNfieldequal 2021-03-02 14:02:58 -06:00
Cody Soyland
d2f391d650
Merge pull request #1496 from codysoyland/docker-build-ci
Docker login prior to building image
2021-03-02 13:59:26 -06:00
Cody Soyland
a94c6cf8a2
Docker login prior to building image 2021-03-02 13:43:27 -06:00
Maxton Huff
d20dc525f5
Merge branch 'master' into topNfieldequal 2021-03-02 13:35:17 -06:00
seebs
2d1d8afdf3
Merge pull request #1490 from seebs/disco1443c
avoid deadlocks or crashes when clients cancel queries
2021-03-02 10:17:24 -06:00
Cody Soyland
0488dbe8d3
Merge pull request #1492 from codysoyland/fix-flags
Fix incorrect build flags
2021-03-02 07:46:07 -06:00
Antonio Navarro Perez
274540ea0b Requested changes
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-02 13:46:37 +01:00
Kuba Podgórski
0cb311f2b3 Fix Heartbeat TTL for disco test 2021-03-02 11:30:25 +01:00
Matthew Jaffee
94ccd514ea
Merge branch 'master' into topNfieldequal 2021-03-01 22:18:36 -06:00
Cody Soyland
bfa9682ba5
Fix incorrect build flags 2021-03-01 17:01:06 -06:00
Seebs
5258532157 bump usage guesstimate again
Same machine, a week later: Got 618k instead of 500k. I'm doomed.
2021-03-01 14:20:18 -06:00
Seebs
35d360c68d fix up executor shard-counting logic a bit better
Ensure that mapReduce always waits on its ErrGroup, even if it wants to return
early due to a failure somewhere. Also check logic a bit more carefully on
the error returns; we don't want a transient failure from one node to result
in the whole query failing, we just want it to retry on the next node, so that
shouldn't cancel the whole ErrGroup.
2021-03-01 14:03:49 -06:00
Antonio Navarro Perez
f67db5035e Add part of cache back.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-01 19:09:31 +01:00
Antonio Navarro Perez
50fd72f980
Apply suggestions from code review
Co-authored-by: Travis Turner <travis@pilosa.com>
2021-03-01 18:41:58 +01:00
Antonio Navarro Perez
6f5770bf65 Fix nil pointer exception
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-01 18:39:04 +01:00
Maxton Huff
15aa7d1ad8 add field to SetRowAttrs and TopK to prototypes in ast.go 2021-03-01 11:18:31 -06:00
Antonio Navarro Perez
ea7643f8bf Add documentation and try to remove code.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-03-01 16:25:32 +01:00
Nia
a906a9036b
Merge pull request #1482 from niaow/force-transactional-etcd-reads
Force transactional etcd reads
2021-02-26 19:03:21 -05:00
Travis Turner
4add6134b8
Merge pull request #1468 from travisturner/disco-clustertests
adjust clustertests to have etcd config
2021-02-26 17:49:20 -06:00
seebs
d455fb3105
Merge pull request #1476 from seebs/disco1443b
mapper/mapReduce/worker: always wait for jobs to be finished
2021-02-26 17:35:02 -06:00
Nia Weiss
4be4097edd
force transactional etcd reads 2021-02-26 18:29:01 -05:00
Maxton Huff
23f44725cb remove var allowUnderField 2021-02-26 16:36:16 -06:00
Cody Soyland
c328a18889
Merge pull request #1440 from codysoyland/cd
Add new Docker build process and continuous delivery
2021-02-26 16:32:46 -06:00
Maxton Huff
3822e38952 remove z arg from Rows tests 2021-02-26 16:15:37 -06:00
Travis
ef40bbb617
renew heartbeat lease if the lease expires while a node is unavailable 2021-02-26 16:15:06 -06:00
Travis
d416b88dda
adjust clustertests to have etcd config 2021-02-26 16:15:06 -06:00
Maxton Huff
441630d804 try fixing tests 2021-02-26 16:13:00 -06:00
Nia
590dc3b226
Merge pull request #1478 from niaow/start-http-after-server-open
Start HTTP after server open
2021-02-26 16:04:34 -05:00
Cody Soyland
dca19f7e94
Add new Docker build process and continuous delivery 2021-02-26 14:34:14 -06:00
Seebs
7d15fc2f26 don't reduce errors with non-errors
if we got an error, we don't have to merge it. so either ctx.Err or
resp.err being non-nil means we shouldn't be reducing, but we still need
to grab the responses to make sure we waited for them all.
2021-02-26 14:26:02 -06:00
Nia Weiss
4340e90396
start HTTP handler after server initialization
This fixes a variety of bugs where API requests would read uninitialized state, causing crashes or race conditions.

Co-authored-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-26 15:23:47 -05:00
Ben Johnson
eff313d181
Merge pull request #1474 from molecula/bench-autogenerate
Add benchmarking of autogenerated ID data
2021-02-26 12:39:36 -07:00
Nia
d205ea5441
Merge pull request #1442 from niaow/fix-foreignindex-race
Fix a race condition when deferring foreign-index initialization
2021-02-26 14:30:18 -05:00
Maxton Huff
8bc8368c57 change test arguments to be appropriate 2021-02-26 12:58:59 -06:00
Seebs
29fddd40f6 mapper/mapReduce/worker: always wait for jobs to be finished
It's not enough to cancel jobs so their goroutines *will* exit; we have
to be certain that they *have exited* before we finish returning from,
e.g., mapReduce(), or a query can "complete" at a time when there are
still running goroutines accessing data that we're about to invalidate
when we terminate the Qcx.

A better solution would integrate this logic and control into the Qcx
and pass it through everything, rather than having the Qcx bypass
the mapper/mapperLocal and be passed into the mapFn/reduceFn via
closures. But a better solution would be a lot larger.
2021-02-26 12:47:02 -06:00
Maxton Huff
6f76767841 add test in executor.go to compare results of query w/without field= 2021-02-26 12:06:25 -06:00
Ben Johnson
90278b206c Add benchmarking of autogenerated ID data 2021-02-26 10:37:15 -07:00
Maxton Huff
d49a8f953e regenerate pql from modified peg file 2021-02-26 11:27:39 -06:00
Nia
65e4496ea7
Merge pull request #1449 from niaow/deferredcreateshard
Defer cluster messages until startup
2021-02-26 08:13:51 -05:00
Maxton Huff
ab41d0492c add more tests for TopK, Rows, and SetRowAttrs 2021-02-25 16:04:31 -06:00
Nia Weiss
3fbf6993d0
defer cluster messages until startup 2021-02-25 16:01:49 -05:00
Nia Weiss
ca918c187d
fix a race condition when deferring foreign-index initialization 2021-02-25 16:00:56 -05:00
Kuba Podgórski
a1d4418236
Merge pull request #1464 from kuba--/etcd-shared-client
One shared etcd client
2021-02-25 19:45:22 +01:00
Kuba Podgórski
50cbb72619 Remove comments/leftovers 2021-02-25 19:00:52 +01:00
Kuba Podgórski
49dc48f057 Switch to server API for KV Get/Range 2021-02-25 18:34:24 +01:00
Kuba Podgórski
aa15e08558 Reduce number of Txn 2021-02-25 18:12:13 +01:00
Maxton Huff
6b75a8b500 Revert "allow 'field=' for TopN()"
This reverts commit db01237904.
2021-02-25 11:01:22 -06:00
Kuba Podgórski
a5f3bce3bf Use hookedClient 2021-02-25 16:56:30 +01:00
Kuba Podgórski
1623007af1 Add waitgroup - don't close the server wait for all keepaliveFunc 2021-02-25 13:41:10 +01:00
Kuba Podgórski
23f901635e Revert "Remove etcd cache"
This reverts commit 0f4b273d3a.
2021-02-25 13:41:10 +01:00
Kuba Podgórski
0f4b273d3a Remove etcd cache 2021-02-25 11:30:09 +01:00
Kuba Podgórski
1fc3d37134
Merge branch 'disco' into etcd-shared-client 2021-02-25 09:42:00 +01:00
Kuba Podgórski
01e0c44069 One shared etcd client 2021-02-25 09:39:44 +01:00
Nia
0cfd4e9780
Merge pull request #1463 from niaow/dontcachestate
Stop caching node state in Etcd
2021-02-24 18:28:03 -05:00
Nia Weiss
8b645e02a2
stop caching node state in Etcd 2021-02-24 17:19:27 -05:00
Maxton Huff
db01237904 allow 'field=' for TopN() 2021-02-24 15:29:10 -06:00
seebs
bffdee1e8e
Merge pull request #1432 from seebs/discoPorts
possible fix for CI deadlocks after port_mapper messages in CI
2021-02-24 12:03:14 -06:00
Seebs
8d6f97604f use testhook to run server tests so we can have post-processing and audits
This gives more consistency with the other tests and allows us to get audit
checks on the server/ tests. The tests on the clients being closed are
temporarily disabled because they tend to think the last test's clients
are "still open" for a few seconds after the test completes.
2021-02-24 11:25:46 -06:00
Seebs
2ee589ae1d reduce goroutine spam during TestVariousQueries
etcd runs a LOT more goroutines during server startup. Fix a
goroutine/for loop bug causing us to run four 7-node clusters
instead of 1/3/4/7-node clusters, also have the test/cluster
code reduce import workers. We can't do much about the spamminess
of the Raft stuff, but this should tone it down some.
2021-02-24 11:25:46 -06:00
Seebs
9333b1b27e leaseKeepAlive: manage context and shut it down cleanly
Every usage of this just ran keepAlive func as a goroutine with a timer, using
a parent context, but the keepAlive func didn't know about that context, so
it couldn't use that context for its own messages or interactions. Change
it to create its own cancelable context from a provided parent, and use
that to control its inner behavior.

Note that we *do* still need to send the revoke at least sometimes -- otherwise
cluster states don't update correctly. But we can time that send out
rather than using context.Background(), because after a TTL's worth of time,
there's no lease to revoke anyway.

Also, add hooks for testhook tracking so we can confirm/deny that things
are getting shut down, which they weren't.
2021-02-24 11:25:46 -06:00
Seebs
c1c0e828cd lock read from bsig.BitDepth, not just write to it 2021-02-24 11:25:46 -06:00
Seebs
8eaa4e592f shut down GRPC client after running QueryGRPC against a cluster
If you don't shut the client down, it leaves two goroutines running forever.
2021-02-24 11:25:46 -06:00
Seebs
66ed216023 bump UI/usage guesstimated limit because my laptop uses about 6% too much 2021-02-24 11:25:46 -06:00
Seebs
4f5f3e30ea remove port_mapper because it can't work with our unrestartable server
Long story short: Once we create a server and start it, we can't start
it again. We can't close it and restart it, and we can't just start
it without closing it.

Unfortunately, if the server's config needs to change, we have a Problem
here.

This ultimately means that the retry logic for GetListeners can't actually
retry successfully; if we fail on the first attempt, we necessarily fail
on any later attempts also, and if we try to fix that, we get panics.

But!

We don't actually NEED to retry. We just need to ensure that we can
open a :0 port, extract the actual port number, and use that in places
where the port number mattered, without having to rebind it.

The only actual place we needed to rebind things was opening gRPC
servers, so we introduce a gRPC Listener that can be used instead of
trying to bind to a specified port.

In a bunch of other cases where we had similar logic to try to allocate
and then use a port, we can switch to just using a provided listener.
For instance, net/http has `Serve(net.Listener, handler)`, not just
ListenAndServe(addr, handler).

This should eliminate the weird CI failures from eaddrinuse.

NOT fixed: server/cluster_test.go/TestClusterResize_AddNode isn't working
right now. The new node isn't actually being added to the existing cluster.
I attempted this but was outsmarted by it, and I think fixing the
rest of this is worth it as a separate thing.
2021-02-24 11:25:46 -06:00
Travis Turner
4200de481d
Merge pull request #1458 from travisturner/disco-remove-coordinator
remove remaining references to "coordinator"
2021-02-24 09:43:04 -06:00
Travis
2bbe1fdde0
remove remaining references to "coordinator" 2021-02-23 17:23:09 -06:00
Ben Johnson
4454df0af0
Merge pull request #1454 from molecula/remove-rbftx-frag
Remove unused RBFTx.frag field
2021-02-23 09:42:50 -07:00
Travis Turner
c16c543274
Merge pull request #1456 from travisturner/disco-remove-docs
remove docs directory
2021-02-23 10:33:12 -06:00
Travis Turner
aa43367f45
Merge pull request #1448 from travisturner/disco-no-metadata-base
Disco no metadata base
2021-02-23 10:15:52 -06:00
Travis
295101ecbd
remove docs directory 2021-02-23 10:13:16 -06:00
Travis
81fbeb61f9
fix logic in fragment.bitDepth() 2021-02-23 10:09:56 -06:00
Travis
912e51790f
remove Field.saveMeta(). get Feild.options.BitDepth from fragment 2021-02-23 10:09:56 -06:00
Travis
8b0f18721e
remove Field.loadMeta() 2021-02-23 10:09:55 -06:00
Travis
dfd49c3648
add a gob-encoding Serializer implementation for tests 2021-02-23 10:09:55 -06:00
Travis
4e857e8de4
remove some calls to Field.saveMeta() 2021-02-23 10:09:55 -06:00
Travis
d639e228ae
remove Index.saveMeta(). remove support for deleing existence field. 2021-02-23 10:09:55 -06:00
Travis
2c112a73fe
remove Index.loadMeta() 2021-02-23 10:09:55 -06:00
Travis
38d5459e25
convert holder decode* methods to functions 2021-02-23 10:09:55 -06:00
Travis
3f0745647b
set timestamp() on field 2021-02-23 10:09:55 -06:00
Travis
ebb340d83e
remove old BSI upgrade code 2021-02-23 10:09:54 -06:00
Travis
114d74af29
pass cfm to openField() 2021-02-23 10:09:54 -06:00
Travis
24c5b654c6
change IndexOptions to reference by value 2021-02-23 10:09:54 -06:00
Ben Johnson
02de222387
Merge branch 'master' into remove-rbftx-frag 2021-02-23 08:56:45 -07:00
Antonio Navarro Perez
5794a4af69
Merge pull request #1452 from ajnavarro/disco/coordinator-err-to-primary
Change coordinator error to primary
2021-02-23 16:44:50 +01:00
Alan Bernstein
2641e57ddb
Merge pull request #1450 from alanbernstein/dont-limit-before-sort
CORE-182 Add ignoreLimit argument to executeGroupByShard
2021-02-23 09:33:07 -06:00
Ben Johnson
5e477e107a Remove unused RBFTx.frag field 2021-02-23 08:32:07 -07:00
Antonio Navarro Perez
f0a5ca5d3a Change coordinator error to primary
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-23 09:58:22 +01:00
Alan Bernstein
f228a35d52 Add ignoreLimit argument to executeGroupByShard 2021-02-22 16:16:11 -06:00
tgruben
0170167bdf
Merge pull request #1447 from tgruben/cleanup
Provide option to update existence field on import roaring request
2021-02-22 15:36:50 -06:00
Todd Gruben
081d86c04b mixed row test 2021-02-22 15:06:45 -06:00
Todd Gruben
d220426686 doc comment 2021-02-22 11:50:01 -06:00
tgruben
18e31a63b6
Update roaring/roaring.go
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2021-02-22 11:42:48 -06:00
Todd Gruben
8e27e55459 Merge branch 'cleanup' of github.com:tgruben/privilosa into cleanup 2021-02-22 11:38:02 -06:00
Todd Gruben
5cbbb7996e jaffee test handling suggestions 2021-02-22 11:37:30 -06:00
tgruben
c2da1d2671
Update api.go
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2021-02-22 11:07:41 -06:00
tgruben
1b87b7148e
Update api.go
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2021-02-22 11:06:55 -06:00
Todd Gruben
155a4b4a31 comment clarification 2021-02-22 10:07:32 -06:00
Todd Gruben
9e186669d8 update go mod to fix cors bug 2021-02-22 08:33:52 -06:00
Travis
9f14415b58
Merge branch 'master' into disco 2021-02-20 10:28:38 -06:00
Todd Gruben
4e3beb0d10 Provide option to update existence on import roaring 2021-02-19 18:08:25 -06:00
Todd Gruben
6219b4ca8b add optional UpdateExistence on importRoaring 2021-02-19 17:47:28 -06:00
Todd Gruben
5b43a84a3b . 2021-02-19 17:09:50 -06:00
Ben Johnson
8647b80adb
Merge pull request #1435 from molecula/fix-node-removal-error
Clarify node removal error when self-removing
2021-02-19 08:23:21 -07:00
Ben Johnson
841208858f Clarify node removal error when self-removing
Currently, if you issue a node removal from the node that is being
removed, then you will see a "node cannot be removed error". It's
not clear why you aren't able to remove the node. The error message
has been updated to clarify why.
2021-02-18 12:55:06 -07:00
Kuba Podgórski
e724ad53f2
Merge pull request #1437 from kuba--/check-state
Check state in shardsByNode once stator is implemented
2021-02-18 12:50:03 +01:00
Kuba Podgórski
484f709621 Add regression test 2021-02-18 12:33:01 +01:00
Kuba Podgórski
bfc24a1745 Check state in shardsByNode once stator is implemented 2021-02-17 16:02:28 +01:00
Kuba Podgórski
b17d2b6d18
Merge pull request #1431 from kuba--/import-412
Avoid precondition failed (412) on ingest
2021-02-17 11:50:44 +01:00
Travis Turner
5c5712dba1
Merge pull request #1434 from travisturner/disco-replica-failover
don't cancel the context if replicas should be attempted
2021-02-16 22:00:02 -06:00
Travis
0d08a68c28
fix test expected error message 2021-02-16 21:59:35 -06:00
Travis
a7d4226326
only cancel() in mapper on a secondary, replica error
There is another case where cancelling here might be useful,
and that's if the query is on a primary node and the replication
factor is 1, meaning there are no secondary nodes to fail over to.
That case is handled here as well.
2021-02-16 16:29:49 -06:00
Travis
d27afc42f1
don't cancel the context if replicas should be attempted 2021-02-16 15:10:24 -06:00
Kuba Podgórski
de17c51293 Avoid precondition failed (412) on ingest 2021-02-16 20:18:14 +01:00
Travis Turner
42b8522e80
Merge pull request #1429 from travisturner/disco-field-createdat
ensure field.CreatedAt is set on loadField
2021-02-15 21:50:28 -06:00
Travis
e54f7d9a0b
ensure field.CreatedAt is set on loadField 2021-02-15 21:28:20 -06:00
Travis Turner
17c0d73fa2
Merge pull request #1427 from travisturner/disco-simplify-view
stop storing a value for views in etcd
2021-02-15 15:41:36 -06:00
nagamocha3000
4dfd713189
Merge pull request #1395 from nagamocha3000/fix-core-78
CORE-78 Add parsing for partial time inputs
2021-02-16 00:18:36 +03:00
Travis
b5d6c632bf
stop storing a value for views in etcd 2021-02-15 14:39:52 -06:00
nagamocha3000
0927240956 Add parsing for partial time inputs 2021-02-15 22:55:35 +03:00
Travis Turner
062851bae5
Merge pull request #1419 from seebs/discoFever
Performance improvements for disco branch
2021-02-15 12:28:10 -06:00
Seebs
82a975fd2a avoid race conditions on nodes
Turns out we sometimes modify returned nodes. Handle this better, but
also fix up some cases where we were generating node lists we didn't really
need to answer simple questions.
2021-02-15 10:20:31 -06:00
Seebs
07a014e952 cache Nodes calls in EtcdWithCache
The Peers() data is cached, but then every call still has to unmarshal JSON
and that's stunningly expensive. Let's not!
2021-02-15 10:19:56 -06:00
Seebs
e2b6912d1c uninvert test for coordinator node / primary field translation node
If we're the primary field translation node, we don't need to set up
translation replication; we only need that if we're *not*. So it
makes sense to test if !IsPrimaryFieldTranslationNode... except that
the test is to determine whether to return early. So it should not
be inverted.
2021-02-15 10:19:03 -06:00
Seebs
0790fbe866 only persist views to etcd when they're not already known
Persisting views to etcd every time we check for them causes
what ends up being about a factor of 60 slowdown. Let's do it a little
less.
2021-02-15 10:19:03 -06:00
Travis
4097ec155b
Merge branch 'master' into disco 2021-02-13 10:00:20 -06:00
Alan Bernstein
06503813c5
Merge pull request #1420 from alanbernstein/fix-schema-null-fields
Represent zero fields in /schema response as [] instead of null
2021-02-13 06:40:36 -06:00
Travis
9fa271a7b8
remove dead code (api.HostStates()) 2021-02-12 21:51:27 -06:00
Travis
d3ffdafdd8
remove some more TXSRCs that slipped in 2021-02-12 21:44:20 -06:00
Travis Turner
b7db27b7a7
Merge pull request #1416 from travisturner/disco-load-schema-on-open
Load schema from etcd on holder open; validate indexes, fields, views
2021-02-12 21:35:13 -06:00
Travis
a2a6e91f6d
remove old, now conflicting test value 2021-02-12 21:21:56 -06:00
Travis
2d17405e94
fix SchemaDetails test 2021-02-12 21:11:45 -06:00
Travis
8f0270acda
adjust openExistenceField() to check on disk first 2021-02-12 20:35:36 -06:00
Kuba Podgórski
40fe280453
Remove not needed holder test 2021-02-12 20:35:36 -06:00
Kuba Podgórski
2f35b51db8
Fix endpoint tests + change BitDepth type to uint64 2021-02-12 20:35:36 -06:00
Travis
a6297dc48e
WIP: load schema from etcd on holder open; validate indexes, fields, views 2021-02-12 20:32:31 -06:00
Travis
b89c699a8e
fix bug from merge 2021-02-12 20:32:12 -06:00
Travis
5b237cae13
Merge branch 'master' into disco 2021-02-12 20:29:41 -06:00
Alan Bernstein
f758a04e18 Represent zero fields in /schema response as [] instead of null 2021-02-12 19:40:42 -06:00
Matthew Jaffee
421848c86a
Merge pull request #1418 from molecula/fix-lattice
update lattice version to correct from accidental downgrade
2021-02-12 16:16:34 -06:00
Matt Jaffee
0e3461e9f4
update lattice version to correct from accidental downgrade 2021-02-12 14:50:10 -06:00
Alan Bernstein
a75c62c90f
Merge pull request #1391 from alanbernstein/field-cardinality
CORE-92 Add /schema/details endpoint, which includes field cardinality
2021-02-12 09:38:42 -06:00
Antonio Navarro Perez
2089e5eeb4
Merge pull request #1417 from ajnavarro/fix-log-web-ui-http-handler 2021-02-12 10:18:51 +01:00
Alan Bernstein
882b14444b Use consistent behavior in test to add queries to transaction 2021-02-11 16:42:30 -06:00
Alan Bernstein
dc6c92771b Fail entire /schema/details request if one field query fails 2021-02-11 16:42:30 -06:00
Alan Bernstein
2773999190 Simplify response structs 2021-02-11 16:42:30 -06:00
Alan Bernstein
12462886a6 Shorten shard lists in error messages 2021-02-11 16:42:30 -06:00
Alan Bernstein
246c345c49 Eliminate omitempty from /schema/details response type 2021-02-11 16:42:30 -06:00
Alan Bernstein
56c940c6a0 Add /schema/details endpoint, which includes field cardinality computed via Count(Distinct()) 2021-02-11 16:42:30 -06:00
Maxton Huff
2e6a8e2030
Merge pull request #1393 from Maxtonian/30trial
CORE-140 add draft trial version of molecula
2021-02-11 16:38:53 -06:00
Maxton Huff
f8fc69670c Merge branch '30trial' of github.com:Maxtonian/pilosa into 30trial 2021-02-11 16:19:09 -06:00
Maxton Huff
b89dae01cc clarify purpose of trialVersion by changing the name to handleTrialDeadline and adding a doc string 2021-02-11 16:13:04 -06:00
Maxton Huff
d5b96ab5ce
Merge branch 'master' into 30trial 2021-02-11 11:02:21 -06:00
Maxton Huff
136a4b8068 change wording 2021-02-11 11:01:16 -06:00
Maxton Huff
dd8d6ebfb1 Respond to code review feedback
change logic in version.go so that the trial related messages only appear on trial versions of molecula
convert Command methods in trial.go to functions and  pass a loggerLogger variable instead since that was the only piece of Command being used
add a function named expireAfter which seperately runs similar functionality to what was previously in daily check with chnages directed at stopping users from changing their internal clock date
change variable names and placement to be more readable and organized
2021-02-11 11:01:16 -06:00
Maxton Huff
ddcf9fe1e8 add licence header 2021-02-11 11:01:16 -06:00
Maxton Huff
c973fae6aa remove remaining release-build-trial 2021-02-11 11:01:16 -06:00
Maxton Huff
c60893a8ee edit and move trial code from server.go to trial.go and combine release build targets 2021-02-11 11:01:16 -06:00
Maxton Huff
7fd3fc775f remove test code 2021-02-11 11:01:16 -06:00
Maxton Huff
d02ba32743 alter error output to satisfy test 2021-02-11 11:01:15 -06:00
Maxton Huff
9840ae67e4 remove error return type 2021-02-11 11:01:15 -06:00
Maxton Huff
1dbab1ff92 add draft trial version of molecula 2021-02-11 11:01:15 -06:00
Maxton Huff
d357447673 change wording 2021-02-11 10:59:32 -06:00
Maxton Huff
0f952bb594 Respond to code review feedback
change logic in version.go so that the trial related messages only appear on trial versions of molecula
convert Command methods in trial.go to functions and  pass a loggerLogger variable instead since that was the only piece of Command being used
add a function named expireAfter which seperately runs similar functionality to what was previously in daily check with chnages directed at stopping users from changing their internal clock date
change variable names and placement to be more readable and organized
2021-02-11 10:36:04 -06:00
Antonio Navarro Perez
e0787ed8a8 Requested changes.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-11 16:37:41 +01:00
Antonio Navarro Perez
5440e177de Use advertised URL
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-11 11:52:42 +01:00
Antonio Navarro Perez
1f234df86e Really fix url on Web UI log
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-11 11:10:38 +01:00
Kuba Podgórski
d491c26b8e
Merge pull request #1413 from kuba--/stop-server
Do not stop etcd server before closing
2021-02-11 10:50:43 +01:00
Matthew Jaffee
a781d472b8
Merge pull request #1415 from molecula/revert-1412-import-roaring-existence
Revert "Update existence field on import-roaring requests"
2021-02-10 18:40:59 -06:00
Kuba Podgórski
5774a8e066 Do not stop etcd server before closing 2021-02-11 00:36:13 +01:00
tgruben
a61ed011fc
Revert "Update existence field on import-roaring requests" 2021-02-10 14:51:11 -06:00
tgruben
a41a65d7bd
Merge pull request #1412 from tgruben/import-roaring-existence
Update existence field on import-roaring requests
2021-02-10 13:03:54 -06:00
Todd Gruben
e7f272f37f updates existence field on importroaring fixes issue (1411) 2021-02-10 12:43:27 -06:00
Maxton Huff
302093035e add licence header 2021-02-10 12:37:13 -06:00
Travis Turner
88f13d5e8b
Merge pull request #1398 from travisturner/disco-schema
Implement Schemator
2021-02-10 12:01:00 -06:00
Travis
7a5192aba6
handle error on LoadSchema() message 2021-02-10 12:00:36 -06:00
Travis
c37424f24f
remove commented code 2021-02-10 11:57:23 -06:00
Travis Turner
5a09b5196e
Merge pull request #23 from travisturner/disco-schema-views
store views in etcd via Schemator
2021-02-10 11:55:58 -06:00
Travis
f3d1572232
update comment 2021-02-10 11:55:34 -06:00
Travis
1c3b0f364d
implement ApplySchema, LoadSchema, and LoadSchemaMessage 2021-02-10 11:51:52 -06:00
Travis
bcb71b023a
fix misplaced _exists check 2021-02-10 11:47:26 -06:00
Travis
8fe1b9a37c
store views in etcd via Schemator 2021-02-10 11:47:26 -06:00
Kuba Podgórski
86f45e9e62 Fix TestClusterResize_AddNode 2021-02-10 16:33:22 +01:00
Kuba Podgórski
ecba5e3636 Fix TestCRUDIndexes 2021-02-10 16:22:34 +01:00
Maxton Huff
4bcdfcc9a2 remove remaining release-build-trial 2021-02-10 08:21:36 -06:00
Kuba Podgórski
2d666f8ee8 Test cleanup 2021-02-10 14:56:48 +01:00
Kuba Podgórski
8c0ece5b7e Merge branch 'disco-schema' of github.com:travisturner/privilosa into pr/travisturner/1398 2021-02-10 14:30:06 +01:00
Kuba Podgórski
9faabd8535 Fix Test_TxFactory_UpdateBlueFromGreen_OnStartup 2021-02-10 14:26:52 +01:00
Kuba Podgórski
1dd9aa866f Fix Test_TxFactory_UpdateBlueFromGreen_OnStartup 2021-02-10 14:09:20 +01:00
Kuba Podgórski
efc598a68b
Merge pull request #1410 from ajnavarro/web-enabled-url-fix
Fix enabled Web UI url log
2021-02-10 13:40:22 +01:00
Antonio Navarro Perez
484abe9cdb Fix enabled Web UI url log
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-10 13:36:19 +01:00
Travis Turner
c85c42c58a
Merge pull request #25 from kuba--/index-exists
Fix TestHandler_PostSchemaCluster
2021-02-09 21:23:55 -06:00
Maxton Huff
7ae1599c12 edit and move trial code from server.go to trial.go and combine release build targets 2021-02-09 15:39:32 -06:00
Cody Soyland
f1f7bd6327
Merge pull request #1406 from codysoyland/upgrade-lattice
Upgrade lattice
2021-02-09 15:19:04 -06:00
Cody Soyland
0227d8306f
Upgrade lattice 2021-02-09 15:00:11 -06:00
Kuba Podgórski
40063a6aa9 Fix TestHandler_PostSchemaCluster 2021-02-09 20:13:38 +01:00
Kuba Podgórski
8591599b4c
Merge pull request #24 from kuba--/delete-views
Fix TestAPI_Import. Delete views when deleting a field.
2021-02-09 16:39:58 +01:00
Kuba Podgórski
d827f63148 Fix ApplySchema API 2021-02-09 16:21:25 +01:00
Kuba Podgórski
5d9fd0906c Fix TestClusterResize_AddNodeConcurrentIndex 2021-02-09 15:51:27 +01:00
Kuba Podgórski
0f97066914 Fix TestAPI_Import. Delete views when deleting a field. 2021-02-09 13:36:53 +01:00
Travis Turner
ccd89bbe2a
Merge pull request #22 from kuba--/index-schemator
Move schemator from API to index. Fix TestExecutor_Execute_SetRow
2021-02-08 15:43:15 -06:00
Kuba Podgórski
37b309be16 Move schemator from API to index. Fix TestExecutor_Execute_SetRow 2021-02-08 21:54:39 +01:00
Kuba Podgórski
2a9423e7f8
Merge pull request #21 from ajnavarro/disco/add-nop-schemator-serializer
Add NopSchemator and NopSerializer
2021-02-08 18:50:49 +01:00
Antonio Navarro Perez
17a5bc51ca Add NopSchemator and NopSerializer
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-08 18:36:53 +01:00
Travis
3542134100
WIP: implement Schemator 2021-02-08 10:42:55 -06:00
Travis
114f6a8751
add withViews argument to api.Schema() method 2021-02-08 10:42:55 -06:00
Travis Turner
ecd8e3fa10
Merge pull request #1397 from travisturner/disco-unify-state
Unify state
2021-02-08 10:00:36 -06:00
Antonio Navarro Perez
b1ff8e55cd
Unify state
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-06 16:53:42 -06:00
Travis Turner
968b1ade50
Merge pull request #1394 from travisturner/disco-clean-topology
Remove pilosa-chk, Topology and ClusterCluster
2021-02-06 16:18:00 -06:00
Kuba Podgórski
218d14df3f
Merge pull request #1396 from kuba--/mod-tidy
cleanup memberlist
2021-02-06 23:16:45 +01:00
Kuba Podgórski
750a684b51 cleanup memberlist 2021-02-06 23:12:08 +01:00
Travis
4bcdbf1bff
go mod tidy 2021-02-05 16:33:35 -06:00
Travis
30d4687a99
remove type Topology 2021-02-05 16:13:43 -06:00
Travis
002aee63e3
remove code related to pilosa-chk 2021-02-05 16:13:43 -06:00
Travis
b7d6db51a3
remove dead code related to pilosa-chk 2021-02-05 16:13:43 -06:00
Travis
4dd6bddf7f
remove pilosa-chk 2021-02-05 16:13:43 -06:00
Travis
b2d666a1d0
remove unused tx function 2021-02-05 16:13:17 -06:00
Travis
d192c1f24f
Merge branch 'master' into disco 2021-02-05 15:58:36 -06:00
Maxton Huff
c967bc96f4 remove test code 2021-02-05 15:40:55 -06:00
Maxton Huff
f37ec5b425 alter error output to satisfy test 2021-02-05 14:25:57 -06:00
Maxton Huff
fb47cb875a remove error return type 2021-02-05 13:40:57 -06:00
Travis Turner
86abf22e6d
Merge pull request #1392 from travisturner/disco-deadcode
remove dead code
2021-02-05 12:22:25 -06:00
Maxton Huff
fec0337630 add draft trial version of molecula 2021-02-05 12:16:08 -06:00
Travis
ec91dad198
remove dead code 2021-02-05 11:31:33 -06:00
Travis Turner
4a408a895a
Merge pull request #1378 from travisturner/disco-config-noder
Disco config noder
2021-02-05 10:37:56 -06:00
Kuba Podgórski
ab3353fb56 Add resize messages for broadcaster 2021-02-05 14:02:28 +01:00
Kuba Podgórski
e4fb58132b
Merge pull request #19 from kuba--/resizer-interface
Apply resizer interface (remove and add node)
2021-02-05 12:48:55 +01:00
Kuba Podgórski
bdbffe8d96 Update cluster_internal_test.go 2021-02-05 12:48:22 +01:00
Kuba Podgórski
35b9d41da1
Merge branch 'disco-config-noder' into resizer-interface 2021-02-05 11:57:51 +01:00
Travis Turner
e48fd9bf88
Merge pull request #18 from travisturner/disco-config-noder-remove-gossip
remove the rest of the gossip code (except config)
2021-02-04 21:35:22 -06:00
Travis
c8c59b649d
remove pilosa-fsck 2021-02-04 21:34:15 -06:00
Kuba Podgórski
ab37bf5c7b Apply resizer interface (remove and add node) 2021-02-04 20:26:41 +01:00
Travis
a4b37273ea
remove the rest of the gossip code (except config) 2021-02-04 13:03:02 -06:00
Travis Turner
3e90a88c34
Merge pull request #17 from ajnavarro/do-not-write-on-degraded
Stop writes on DEGRADED state
2021-02-04 13:01:22 -06:00
Antonio Navarro Perez
87ba73fa16 Stop writes on DEGRADED state
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-04 17:30:14 +01:00
Antonio Navarro Perez
39eacfb9a3
Merge pull request #16 from travisturner/disco-config-noder-primaryid-remove-gossip 2021-02-04 10:45:23 +01:00
Antonio Navarro Perez
add5065144
Merge pull request #13 from travisturner/disco-config-noder-primaryid 2021-02-04 10:38:15 +01:00
Travis
afc53e1163
remove ReceiveEvent 2021-02-03 23:31:38 -06:00
Travis
652014539c
remove temporary Gossiper interface 2021-02-03 23:06:51 -06:00
Travis
6e4ea21ce5
remove gossip listenForJoins 2021-02-03 22:34:45 -06:00
Travis
6a0f67278a
revert a test boolean 2021-02-03 21:44:05 -06:00
Travis
fbdca3c622
refactor the PrimaryNodeID logic 2021-02-03 20:58:25 -06:00
Alan Bernstein
8e637cc34a
Merge pull request #1390 from alanbernstein/memory-usage
CORE-162 Add memory info to /ui/usage response
2021-02-03 16:36:57 -06:00
Travis
da804ee6d5
linter fixes 2021-02-03 15:11:24 -06:00
Travis
f9661b7b81
add PrimaryNodeID() method to Noder interface 2021-02-03 15:11:24 -06:00
Kuba Podgórski
893b5ea6ab
Merge pull request #15 from kuba--/no-mu
No mu
2021-02-03 22:06:39 +01:00
Alan Bernstein
6c139935f7 Add memory info to /ui/usage response 2021-02-03 14:18:29 -06:00
Kuba Podgórski
377ef73fbd
Merge pull request #14 from kuba--/remove-cluster-state
Remove state member from cluster.
2021-02-03 19:40:22 +01:00
Kuba Podgórski
6601835ba1 Remove public mutex from Node 2021-02-03 19:37:54 +01:00
nagamocha3000
52ab7e5a99
Merge pull request #1379 from nagamocha3000/fix-core-26
Close process on fragment.openStorage error
2021-02-03 19:18:58 +03:00
nagamocha3000
92426a9d1b Close process on fragment.openStorage error
When *fragment.openStorage is invoked in both f.importValue and
f.importValueSmallWrite and it returns an error, this means there's
some underlying error with the storage device and at the point of this
commit, the sane thing to do is to close the process, otherwise the
operation of Pilosa might proceed in an inconsistent state thus
precipiatting other silent but hairy errors along the way such as
dereferencing *fragment.gen later on which is set to nil once
openStorage fails.
2021-02-03 18:47:10 +03:00
Kuba Podgórski
6826997852 Remove state member from cluster.
Remove all function SetState like. Stop broadcasting cluster state.
2021-02-03 15:16:59 +01:00
Travis
4c1d94da14
remove some dead code related to coordinator 2021-02-02 15:59:36 -06:00
Antonio Navarro Perez
c45e21640c
Change coordinator to primary
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-02-02 15:56:12 -06:00
Travis
28a19cdff7
Merge branch 'disco-config-noder' of github.com:travisturner/privilosa into disco-config-noder 2021-02-02 15:54:01 -06:00
Travis Turner
71084a0429
Merge pull request #12 from kuba--/apply-stator
Apply stator
2021-02-02 15:53:35 -06:00
Kuba Podgórski
a16a83445b Apply stator 2021-02-02 19:36:34 +01:00
Kuba Podgórski
0e34409ff0 Close etcd client after Revoke 2021-02-02 11:47:06 +01:00
Travis
91c0df29a1
remove disco debugging printlns 2021-02-01 22:28:43 -06:00
Travis
629bfa3ac8
add more AwaitState calls in the tests 2021-02-01 21:21:06 -06:00
Travis
4811958de4
add AwaitState to test which re-opens node 2021-02-01 17:34:12 -06:00
Travis
26176c15eb
fix linter issues (wrap all ClusterStates in string() until we update the type) 2021-02-01 16:57:35 -06:00
Kuba Podgórski
b611480499
disco State 2021-02-01 16:37:04 -06:00
Kuba Podgórski
6058fc22e4
Porting disco.Stator (next step) 2021-02-01 16:35:59 -06:00
Ben Johnson
c75d5553b9
Merge pull request #1373 from molecula/bench
Update keyed/unkeyed benchmarks
2021-02-01 14:39:21 -07:00
Ben Johnson
0900e7b9d2
Merge branch 'master' into bench 2021-02-01 14:10:15 -07:00
Cody Soyland
a057cc9899
Merge pull request #1375 from codysoyland/duration-header
CORE-27 Add duration header to all gRPC query results
2021-02-01 11:55:55 -06:00
Cody Soyland
0e22ed71cc
Fix instances of context.Background that need mocked context 2021-02-01 11:40:45 -06:00
Cody Soyland
c30e3f0c2d
Move duration header to fix error handling 2021-02-01 11:40:45 -06:00
Cody Soyland
e2331372d8
Handle errors 2021-02-01 11:40:45 -06:00
Cody Soyland
367425bba1
Add duration header to all gRPC query results 2021-02-01 11:40:43 -06:00
Alan Bernstein
51e41ee6b2
Merge pull request #1331 from alanbernstein/field-usage
Show disk usage broken down by field and keys
2021-02-01 11:31:29 -06:00
Travis
855e1b35f5
more use of noder; remove c.nodes
disable some of the gossip logic

implement some of the stator logic
2021-01-31 23:42:49 -06:00
Travis
97eaff5c82
use Etcd Noder; actually use EtcdWithCache 2021-01-31 23:42:44 -06:00
Travis
7ed1417893
set node metadata in server.Open() 2021-01-30 09:12:07 -06:00
Travis
457194f6a8
update config to support etcd arguments 2021-01-29 19:43:48 -06:00
Alan Bernstein
e981b162f0 Upgrade lattice 2021-01-29 17:48:24 -06:00
Alan Bernstein
1e7c4d7e8e Include metadata AKA 'other' in response 2021-01-29 17:48:24 -06:00
Alan Bernstein
5beb2664b0 Use simpler test 2021-01-29 17:48:24 -06:00
Alan Bernstein
c81ea88847 Fix total summation 2021-01-29 17:48:24 -06:00
Alan Bernstein
15443b371c Force consistent timestamp width in startup log 2021-01-29 17:48:24 -06:00
Alan Bernstein
5dc00883bd Add more involved diskUsage test 2021-01-29 17:48:24 -06:00
Alan Bernstein
703bd14048 Fix errors in usage check 2021-01-29 17:48:24 -06:00
Alan Bernstein
85fad859e2 Correct some disk usage computations 2021-01-29 17:48:24 -06:00
Ben Johnson
32a35805a4 Add RBF index/field usage stats 2021-01-29 17:48:24 -06:00
Alan Bernstein
e397d35ed5 Include roaring field and key details in usage endpoint 2021-01-29 17:48:24 -06:00
Travis
e459c9a77b
change Config.DisCo to Config.Etcd 2021-01-29 14:11:51 -06:00
Ben Johnson
ea653eb9a4
Merge branch 'master' into bench 2021-01-29 12:46:26 -07:00
Nia
20d55f0805
Merge pull request #1369 from niaow/count-global
CORE-29 Invoke pre-calls directly in count operations (fixes Count(Distinct()) on negative integers)
2021-01-29 11:20:29 -05:00
Nia
2961a69bd2
Merge branch 'master' into count-global 2021-01-29 11:14:02 -05:00
Alan Bernstein
1f87b54e5f
Merge pull request #1361 from alanbernstein/distinct-crash
CORE-32 Handle nil result in signed row translation
2021-01-29 10:13:48 -06:00
Nia
13db91379f
Merge branch 'master' into count-global 2021-01-29 10:57:46 -05:00
Alan Bernstein
c4455acbd8 Use inconsistent JSON schema to reach Distinct translation error condition 2021-01-29 09:39:31 -06:00
Alan Bernstein
4fba6bea82 Prevent nil pointer exception during Distinct key translation 2021-01-29 09:39:01 -06:00
Kuba Podgórski
9a70e15cb3
Merge pull request #1372 from travisturner/disco-groupby-fix
Fix Groupby test which uses RowKey instead of RowID
2021-01-29 11:31:11 +01:00
Travis
58ff92d3d6
Fix Groupby test which uses RowKey instead of RowID
This commit introduces a CheckGroupByOnKey function which acts like the
CheckGroupBy function, but it only ensures equality on RowKey, not
RowID.
2021-01-28 21:12:02 -06:00
Travis
1c0b926eae
Merge master into disco 2021-01-28 18:03:38 -06:00
Ben Johnson
60b6eecc7a Update keyed/unkeyed benchmarks 2021-01-28 16:36:45 -07:00
Travis Turner
92ee314891
Merge pull request #1362 from travisturner/disco-node-id
use etcd for node.ID
2021-01-28 15:26:48 -06:00
Travis Turner
1726aa137e
Merge pull request #11 from kuba--/fix-server_tests
Fix server tests
2021-01-28 14:36:02 -06:00
Kuba Podgórski
cef6925e7b Fix server tests 2021-01-28 17:39:58 +01:00
Maxton Huff
4b33a7fe16
Merge pull request #1368 from Maxtonian/mmap
Mmap limit comparison warning message for Linux
2021-01-27 10:33:43 -06:00
Maxton Huff
7d82c55274
Merge branch 'master' into mmap 2021-01-27 10:15:50 -06:00
Maxton Huff
927db378b4 add linux OS check and the way mmap limit is read 2021-01-27 09:52:13 -06:00
Nia Weiss
0d97ec559b
switch signed count distinct test to use TestVariousQueries 2021-01-27 10:29:40 -05:00
Travis
4380a05bbd
address some coord/node0 test issues 2021-01-26 22:46:37 -06:00
Matthew Jaffee
f84f43ec64
Merge pull request #1370 from travisturner/distinctset-empty-row
Return zero-bit row (with Index/Field) instead of nil in executeDistinctShardSet
2021-01-26 20:50:38 -06:00
Travis
48ac989e6a
Return zero-bit row (with Index/Field) instead of nil in executeDistinctShardSet 2021-01-26 15:47:28 -06:00
Travis
315cad679d
Return zero-bit row (with Index/Field) instead of nil in executeDistinctShardSet 2021-01-26 15:41:47 -06:00
Travis
4f47862b48
remove code which was forcing etcd logging 2021-01-26 15:40:58 -06:00
Nia Weiss
ac09c11bad
Invoke precalls directly in count operations
This changes Count(Precall()) operations to execute the precall directly inside of the count operation, bypassing the transformation to a Precomputed() call.
Eliminating the Precomputed() step causes Count(Distinct()) to work properly on negative integers.
2021-01-26 12:44:03 -05:00
Maxton Huff
8c36da9eeb Merge branch 'mmap' of github.com:Maxtonian/pilosa into mmap 2021-01-26 11:27:12 -06:00
Maxton Huff
3982a8e970 format messages and change mmap comparison logic 2021-01-26 11:26:36 -06:00
Maxton Huff
bd680ef144
Merge branch 'master' into mmap 2021-01-26 10:21:18 -06:00
seebs
89f1dfb239
Merge pull request #1367 from seebs/countRange
RBF countRange: Handle partial counts on bitmapPtr containers
2021-01-26 09:51:09 -06:00
Maxton Huff
3809fe6734 add error check 2021-01-26 09:35:51 -06:00
Travis
b80f5099b2
more coordinator/primary cleanup 2021-01-25 23:20:08 -06:00
Maxton Huff
55a9952b92 mmap limit comparison error message 2021-01-25 16:19:12 -06:00
Seebs
a238afb21a Handle BitmapPtr cells in countRange
We need to be able to count bits in BitmapPtr containers. This only
comes up if you have a non-container-aligned range count, which we
never do in real production yet, but the API allows it so it should
work. In order to do this, we need to provide the tx to countRange
so it can grab pages as needed. Arguably, we should be able to avoid
actually creating/copying that page since we're only using it
internally, never returning it, but this is a pretty rare case
and probably not performance-critical.
2021-01-25 15:41:35 -06:00
Seebs
d1a9c91a96 Test CountRange on non-container ranges.
This test was supposed to check against all the container types,
but especially bitmaps, but turns out not to work because the
containers turn into RLE containers. Oops. Now, we start with
every-other-bit for the first 8k, then start filling in the holes,
so we get some bitmap containers and then start generating
RLE containers.
2021-01-25 15:41:35 -06:00
Nia
13c63baa14
Merge pull request #1365 from niaow/groupby-cluster-rows
CORE-28 Fix GroupBy with a global Rows filter
2021-01-25 15:37:48 -05:00
Nia
60ab9e84dd
Merge branch 'master' into groupby-cluster-rows 2021-01-25 15:26:13 -05:00
Travis Turner
f5c1454a0d
Merge pull request #9 from kuba--/get-coord
Replace Node(0) by GetCoordinator
2021-01-25 14:06:39 -06:00
Kuba Podgórski
32b5c5bcea Replace Node(0) by GetCoordinator 2021-01-25 19:54:25 +01:00
Nia
ed9fc962d5
Merge pull request #1359 from niaow/intersectany-single-word-run
CORE-31 Fix intersectionAnyRunBitmap when processing single-word runs
2021-01-25 11:16:30 -05:00
Nia
70d87a7950
Merge branch 'master' into intersectany-single-word-run 2021-01-25 11:03:51 -05:00
Nia Weiss
dde318ac8c
Move globally computed GroupBy rows calls into EmbeddedData
This fixes a bug where a globally computed Rows call would be computed with a subset of the shards.
2021-01-25 10:17:58 -05:00
Ben Johnson
66bc79634b
Merge pull request #1363 from molecula/pilosa-bench-vars
Add ingest time & latency stats to query benchmarks
2021-01-25 08:16:34 -07:00
Cody Soyland
649202b081
Fix cluster size setter: expose failures 2021-01-25 10:16:19 -05:00
Ben Johnson
a30fd9957e
Merge branch 'master' into pilosa-bench-vars 2021-01-25 07:56:20 -07:00
Travis
ace4dea46f
address some test failures due to random ordered etcd ID 2021-01-25 00:52:49 -06:00
Travis
2f66501160
finish implementing snap := ClusterSnapshot() 2021-01-24 23:22:32 -06:00
Travis
1473e11a27
update test cluster GetNode() to consider the etcd-assigned ID (which affects node order) 2021-01-23 19:52:59 -06:00
Travis
a196e1e74c
use etcd for node.ID
this commit adds a temporation interface for starting gossip.
we needed this so we can start gossip AFTER setting up the node,
but before waitingForJoins.
2021-01-23 19:52:58 -06:00
Travis
208b81b5f4
fix merge error 2021-01-23 19:52:34 -06:00
Travis
c9e6f17ae0
Merge branch 'master' into disco 2021-01-23 19:22:20 -06:00
Cody Soyland
3da3d23b21
Merge pull request #1364 from codysoyland/lattice-submodule
Add git-submodule to manage UI version
2021-01-22 16:57:57 -06:00
Alan Bernstein
852057533b Add lattice submodule upgrade instructions 2021-01-22 16:51:17 -06:00
Cody Soyland
671c7262c9
Add lattice to PHONY 2021-01-22 16:26:09 -06:00
Cody Soyland
34f728521c
Add git-submodule to manage lattice version 2021-01-22 15:05:19 -06:00
Ben Johnson
acdff02fed Add ingest time & latency stats to query benchmarks 2021-01-22 11:41:44 -07:00
nagamocha3000
6c3c460c83
Merge pull request #1344 from nagamocha3000/bnm-fix-1080
Fix filtering on time fields in Rows() embedded within GroupBy
2021-01-22 19:56:08 +03:00
nagamocha3000
b5fdc6609a Update tests to remove sum column on GroupBy 2021-01-22 18:44:36 +03:00
Kuba Podgórski
2c4c722a1b
Merge pull request #1348 from travisturner/disco-storage-config
introduce storage.Config
2021-01-22 11:12:15 +01:00
Travis
19f91782e7
remove all instances of txsrc 2021-01-21 21:59:51 -06:00
Travis
13984353e4
remove instances of os.Getenv("PILOSA_TXSRC") 2021-01-21 21:18:46 -06:00
Nia Weiss
0d9179f10c
roaring: fix intersectionAnyRunBitmap when processing single-word runs
When a run started and ended within a single word, the entirety of the word would be checked.
This would cause small runs to be processed incorrectly, and caused Distinct-on-sets to select rows that did not match the specified filter.
2021-01-21 18:09:27 -05:00
nagamocha3000
16b5fbe40b
Merge branch 'master' into bnm-fix-1080 2021-01-21 17:37:08 +03:00
nagamocha3000
6cbcde3a82 Add more tests for GroupBy on Time fields 2021-01-21 16:20:46 +03:00
nagamocha3000
113bec2474 Remove unnecessary nil check 2021-01-21 15:48:52 +03:00
Travis
f292d6061a
replace pilosa.DefaultTxsrc with storage.DefaultBackend 2021-01-20 22:06:13 -06:00
Travis
08fae2be4c
introduce storage.Config 2021-01-20 22:05:38 -06:00
Alan Bernstein
b273f3ba60
Merge pull request #1327 from alanbernstein/sql-history
Include SQL string in query-history
2021-01-20 19:05:36 -06:00
Alan Bernstein
eaf3ef153e Test SQL behavior 2021-01-20 15:58:55 -06:00
Alan Bernstein
bed03ba490 Update tests 2021-01-20 10:48:35 -06:00
Alan Bernstein
a0d6c253d1 Pass SQL query string from mapper to tracker 2021-01-20 10:48:35 -06:00
Cody Soyland
06241d1f84
Merge pull request #1258 from codysoyland/distinct-failure
Test to demonstrate failure running Distinct
2021-01-20 10:37:47 -06:00
Cody Soyland
0a325dcdb8
Merge branch 'master' into distinct-failure 2021-01-19 16:50:25 -06:00
seebs
38ded7963e
Merge pull request #1342 from seebs/aggregate
Handle aggregate functions better in sql/grpc/json
2021-01-19 16:28:32 -06:00
Seebs
932e84b681 handling aggregate types: add to protobuf, etc
We want to distinguish different *kinds* of GroupCounts, so we're
making the GroupCounts parent object track its type so we can keep that
correct.

Adding this to protobuf, etc, then creates some weird behaviors
because sometimes we expect []GroupCount, and sometimes we expect
*GroupCounts. This implies changes to test cases. Also, the
changes to test cases imply that some test cases are probably now
wrong; for instance, they're expecting a "sum" column, equal to zero,
when no sum was requested.

We try to make the encoder handle a []*GroupCount gotten from another
node without panicing, and avoid breaking the semantics of the existing
messages, renumbering messages or components, etc.

Since a previous version, the `.Groups` member has been privatized,
and the `.Get()` convenience accessor has been renamed `.Groups()`
and is now used consistently in a way that should reduce the risk
of nil pointers causing crashes. Also, NewGroupCounts is used in
a couple more places.
2021-01-19 16:23:15 -06:00
Cody Soyland
4ebf6f6ff7 Customize serialization of []GroupCount based on aggregate type/presence 2021-01-19 12:10:56 -06:00
Travis Turner
07d9cbe380
Merge pull request #1345 from travisturner/disco-config
port disco config to ctl/server
2021-01-19 10:50:17 -06:00
nagamocha3000
0437f5d28a Handle case where row returned might be nil 2021-01-19 16:51:26 +03:00
Travis
f47800a920
add DisCo config to ctl/server 2021-01-18 23:47:35 -06:00
Ben Johnson
56c001d288
Merge pull request #1341 from molecula/bench-vars
Update benchmarks to use expvar URL list
2021-01-18 16:06:43 -07:00
nagamocha3000
d26c6b048e Sort all rowIDs gathered before storing them 2021-01-19 02:00:50 +03:00
nagamocha3000
9b23dcdd0a Gather rows for each fragment in a much smarter way 2021-01-19 01:44:54 +03:00
tgruben
ef05968e20
Merge pull request #1340 from jaten-molecula/noder_impl
Noder impl
2021-01-18 15:22:17 -06:00
Ben Johnson
01e6781abd Update benchmarks to use expvar URL list 2021-01-18 13:43:53 -07:00
jaten-molecula
3928b6854b
Merge pull request #1338 from jaten-molecula/etcd-listner
Etcd listener
2021-01-18 14:40:32 -06:00
Jason E. Aten
b1a0e0ae8b allow retry at the cluster level to work; remove retry for server/server.go Command.setupNetworking() that retries a single gossip node 2021-01-18 20:39:23 +00:00
Jason E. Aten
ed12f3585c etcd/embed.go implemented Noder 2021-01-18 20:30:21 +00:00
Jason E. Aten
9b635068d9 cleanup 2021-01-18 20:16:49 +00:00
Jason E. Aten
ad1c3ff3fb go mod tidy 2021-01-18 19:18:08 +00:00
Jason E. Aten
e58b464b29 add port.GetListeners 2021-01-18 18:42:21 +00:00
nagamocha3000
f51ff4dc85 Add tests for Rows() on time fields 2021-01-18 20:54:31 +03:00
Todd Gruben
766e3b90bc wip 2021-01-18 10:59:01 -06:00
Todd Gruben
de7d69234e initial listner 2021-01-18 10:34:18 -06:00
Travis Turner
d6d51705fa
Merge pull request #1334 from travisturner/disco-merge
Disco merge
2021-01-15 18:42:13 -06:00
Travis
1d55e671a2
go mod tidy and linter
fix race

cleanup
2021-01-15 17:48:44 -06:00
nagamocha3000
b77f9e8a43 Add timeFragments rowIterator 2021-01-15 23:36:54 +03:00
Travis
9855f4d0a0
Merge branch 'travis-test-ci' into disco-try 2021-01-15 14:31:19 -06:00
nagamocha3000
f91b4bc016 Add queries to test GroupBy Rows on time field 2021-01-15 22:58:18 +03:00
nagamocha3000
54d79d1e4d Populate 'places_visited' field for 'users' index 2021-01-15 22:50:54 +03:00
nagamocha3000
4dc3e49a0d Add test helper for inserting to time quantum fields 2021-01-15 22:42:37 +03:00
Jason E. Aten
8909517dfd
cluster_internal_tests use getport 2021-01-15 11:47:37 -06:00
Jason E. Aten
530fd4e768
GlobalPortMapper avoids many races in port allocation for cluster setup 2021-01-15 11:47:37 -06:00
Travis
4355bdd8f0
temporarily have cluster implement Noder 2021-01-15 11:47:37 -06:00
Travis
10380a1da1
Implement snap := ClusterSnapshot()
Below is the list of instance of `ClusterSnapshot()` in the latest
`with-etcd` code. Some of these may not yet exist in the `disco` branch,
but this commit is implementing any that currently apply.

==========================
Done:
==========================
index.go
930:	snap := NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)
1072:	snap := NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)

cmd/pilosa-fsck/fsck.go
786:	snap := pilosa.NewClusterSnapshot(cfg.topo, cfg.topo.Hasher, cfg.topo.ReplicaN)

boltdb/translate.go
558:	snap := pilosa.NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)
1264:	snap := pilosa.NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)

fragment.go
3448:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
3568:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
3620:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)

==========================
Remaining:
==========================

cluster.go
371:	snap := NewClusterSnapshot(NewLocalNoder(nodes), c.Hasher, c.ReplicaN)
474:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
639:	fSnap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
640:	toSnap := NewClusterSnapshot(to.noder, c.Hasher, to.ReplicaN)
703:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1475:		snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1502:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1941:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1986:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
2049:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
2126:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)

api.go
475:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
604:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
690:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
1684:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
1946:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)

executor.go
3781:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4157:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4200:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4243:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4517:	snap := NewClusterSnapshot(NewLocalNoder(e.Cluster.Nodes()), e.Cluster.Hasher, e.Cluster.ReplicaN)

holder.go
1465:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1668:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1889:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1963:	snap := NewClusterSnapshot(c.Cluster.noder, c.Cluster.Hasher, c.Cluster.ReplicaN)
2021-01-15 11:47:37 -06:00
Travis
7875fb8e5a
remove pilosa.DefaultPartitionN 2021-01-15 11:47:37 -06:00
Jason E. Aten
dd7f0f3c88
use bbolt v1.3.5 that has fixed the checkptr bugs 2021-01-15 11:47:37 -06:00
Travis
f633fcd4ae
remove pilosa.URI 2021-01-15 11:47:36 -06:00
Travis
ff2d235702
change all references to use subpackages: topology, net 2021-01-15 11:47:36 -06:00
Travis
0add3fc7c6
fix linter and go.mod issues 2021-01-15 11:47:36 -06:00
Travis
85560323dc
add licence headers 2021-01-15 11:47:36 -06:00
Travis
b251d4c6c1
change bbolt version back to 1.3.3 2021-01-15 11:47:36 -06:00
Travis
9d8a6ad28d
add subpackages: topology, net 2021-01-15 11:47:35 -06:00
Kuba Podgórski
ba7108dedb Revert "Cleanup etcd dir"
This reverts commit 886ba15e88.
2021-01-15 17:50:34 +01:00
Kuba Podgórski
886ba15e88 Cleanup etcd dir 2021-01-15 15:41:16 +01:00
Kuba Podgórski
a4f9aee28e Set etcd log level to error 2021-01-15 14:11:48 +01:00
Kuba Podgórski
6cd8f6a970 Less TestMain_Set_Quick parallel tests 2021-01-15 13:24:41 +01:00
Kuba Podgórski
17b1eeb0d0 Increase timeout (30s) for cluster NORMAL state 2021-01-15 12:55:03 +01:00
Kuba Podgórski
64425736b0 Create disco dir outside pilosa 2021-01-15 12:30:57 +01:00
Travis
684b20edb3
disco open/close debugging 2021-01-14 23:02:58 -06:00
Kuba Podgórski
4afaaa5e25 remove zap 2021-01-14 20:59:17 +01:00
Kuba Podgórski
9a0facaaa3 set even more ports for Node Command 2021-01-14 20:20:23 +01:00
Kuba Podgórski
201e851511 set more ports for Node Command 2021-01-14 20:04:09 +01:00
Kuba Podgórski
33c4c77495 revert bind port to 0 2021-01-14 18:33:22 +01:00
Kuba Podgórski
36f17eee1d global mutex on GetPorts 2021-01-14 18:04:16 +01:00
Kuba Podgórski
a100a38b4a don't close disco on Server.Close 2021-01-14 17:47:06 +01:00
Kuba Podgórski
0e4a7a29fb close disco before holder 2021-01-14 17:35:30 +01:00
Kuba Podgórski
2713be9329 check error as string 2021-01-14 17:12:52 +01:00
Kuba Podgórski
1f6ed4feca bangbang theory 2021-01-14 16:25:44 +01:00
Antonio Navarro Perez
1a5ab4b155 Fix some more problems
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-01-14 13:10:51 +01:00
Antonio Navarro Perez
052aadb3b0 Wrap some missing constructors using ports.
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-01-14 10:48:46 +01:00
Travis
27614c42f7
Finish implementing port wrapper 2021-01-13 22:56:54 -06:00
Antonio Navarro Perez
d20b831084 Add port wrapper POC
Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-01-13 20:14:33 +01:00
Kuba Podgórski
61edff3eee Apply closed channel fix
45619a5b7b
2021-01-13 15:37:13 +01:00
Kuba Podgórski
4afb0ecc51 Close TCP listeneer on port mapper 2021-01-13 13:53:27 +01:00
Travis
877af6dad9
replace a MustNewCluster with MustRunCluster 2021-01-12 23:30:10 -06:00
Travis
ef8d0759d5
add retry to pg test ServerTLS() 2021-01-12 23:04:49 -06:00
Travis
f2234929d8
add retry to MustRunCluster 2021-01-12 22:09:09 -06:00
Travis
bc13834343
disco/etcd work: fix lots of races, start all cluster nodes at once.
port mapper gives out ports from 63000-65000 for the tests

fix another race

http test uses port.MustGetPort

rbf: remove :0 port request

ocd happy

test fix for grpc listener address already in use

test/disco allocates BindGRPC port from the port mapper

dump stack on each GetPort

verify each port is usable right away

server/config.go has Config.Validate() now

panic if gossip port is 0. validate server.Config

fix another gossip port 0

builds

quiet, don't dump stack on each port alloc

builds

happy linter

even gossip fallback should not be zero but rather use the port mapper
2021-01-12 21:06:12 -06:00
Ben Johnson
fbf546f131
Merge pull request #1319 from molecula/pilosa-bench 2021-01-12 16:51:27 -07:00
Ben Johnson
b7973e2612 Add read benchmarks 2021-01-12 13:48:09 -07:00
Matthew Jaffee
701d6448cc
Merge pull request #1307 from jaffee/1292-panic-groupby-int-distinct-aggregate
Fix potential panic when grouping on int field with Distinct aggregate
2021-01-08 16:38:00 -06:00
Matt Jaffee
48552553dc
guard against NPE when setting precomputed data
If a precomputed call returns a nil Row result somehow, that could
cause a nil pointer exception when handling the result in
handlePreCall.

In this particular case, A Distinct call on a BSI field with a filter
which returned no results could return a SignedRow{} with nil *Rows
inside of it. This only manifested if there was data in a single shard
as otherwise the reduce logic created a SignedRow with empty *Row
objects rather than nil ones. Isn't that fun?

Extra fun: the reason the filter was returning no results was not
because it was actually empty, but because of another bug where
constructing the Distinct calls to compute the aggregate of a GroupBy
doesn't take into account that the group might include an integer
field which means that the call needs to be constructed
differently. That bug is not fixed in this commit, hence the tests are
still failing, but not panicking.
2021-01-08 15:03:49 -06:00
Matthew Jaffee
616ba408f8
Merge pull request #1308 from codysoyland/groupby-distinct-int
Fix GroupBy Distinct aggregate on int field
2021-01-08 13:55:38 -06:00
Cody Soyland
83ce30f1c4
Fix GroupBy Distinct aggregate on int field 2021-01-08 13:35:58 -06:00
Ben Johnson
55fad52c59
Merge pull request #1306 from molecula/rbf-remove-cursor-arena
Remove RBF cursor arena.
2021-01-08 10:13:52 -07:00
Ben Johnson
489f33a173 Remove RBF cursor arena.
Previously there were two implementations of cursor reuse: sync pool &
an arena. This commit removes the arena in favor of the global pool.
2021-01-08 07:59:10 -07:00
Ben Johnson
1865de8248
Merge pull request #1301 from molecula/fix-rbf-cursor-close 2021-01-07 19:22:34 -07:00
jaten-molecula
b3854e867b
Merge branch 'master' into fix-rbf-cursor-close 2021-01-07 20:14:59 -06:00
Jason E. Aten
ecada682ae cluster_internal_tests use getport 2021-01-07 22:30:04 +00:00
jaten-molecula
0c1f2f06ba
Merge pull request #1304 from jaten-molecula/portmap
GlobalPortMapper avoids many races in port allocation for cluster setup
2021-01-07 16:24:02 -06:00
Jason E. Aten
1aabcb3d14 GlobalPortMapper avoids many races in port allocation for cluster setup 2021-01-07 22:20:49 +00:00
Cody Soyland
476767f150
Merge pull request #1285 from codysoyland/grpc-crd
Add create, read, and delete index methods to gRPC interface
2021-01-07 15:24:13 -06:00
Cody Soyland
4f57b4d07b
Remove TrackExistence configuration from gRPC CreateIndex 2021-01-07 15:19:08 -06:00
Cody Soyland
d8ebfda1bd
Undo error cause changes due to broken logic in other places, check for ConflictError explicitly 2021-01-07 14:49:18 -06:00
Travis Turner
4eb36a34f6
Merge pull request #1294 from travisturner/disco-cleanup
Disco cleanup
2021-01-07 14:08:55 -06:00
Cody Soyland
219714a18e
Fix linter problems 2021-01-07 13:50:59 -06:00
Travis
8dbfae1d86
temporarily have cluster implement Noder 2021-01-07 13:45:46 -06:00
Cody Soyland
daa8c9bd8b
Add tests for new gRPC create/get/delete calls 2021-01-07 13:05:48 -06:00
Cody Soyland
fdf5818fc2
Add create, read, and delete index methods to gRPC interface 2021-01-07 13:05:48 -06:00
Ben Johnson
93f06e0f9d Fix rbf.Cursor.Close() panic 2021-01-07 11:28:46 -07:00
Maxton Huff
17e010cca2
Merge pull request #1293 from Maxtonian/verbose-message
Fix formatting bug in verbose log message
2021-01-07 09:38:29 -06:00
Travis
134abda51b
Implement snap := ClusterSnapshot()
Below is the list of instance of `ClusterSnapshot()` in the latest
`with-etcd` code. Some of these may not yet exist in the `disco` branch,
but this commit is implementing any that currently apply.

==========================
Done:
==========================
index.go
930:	snap := NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)
1072:	snap := NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)

cmd/pilosa-fsck/fsck.go
786:	snap := pilosa.NewClusterSnapshot(cfg.topo, cfg.topo.Hasher, cfg.topo.ReplicaN)

boltdb/translate.go
558:	snap := pilosa.NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)
1264:	snap := pilosa.NewClusterSnapshot(topo, topo.Hasher, topo.ReplicaN)

fragment.go
3448:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
3568:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
3620:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)

==========================
Remaining:
==========================

cluster.go
371:	snap := NewClusterSnapshot(NewLocalNoder(nodes), c.Hasher, c.ReplicaN)
474:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
639:	fSnap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
640:	toSnap := NewClusterSnapshot(to.noder, c.Hasher, to.ReplicaN)
703:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1475:		snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1502:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1941:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
1986:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
2049:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
2126:	snap := NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)

api.go
475:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
604:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
690:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
1684:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)
1946:	snap := NewClusterSnapshot(api.cluster.noder, api.cluster.Hasher, api.cluster.ReplicaN)

executor.go
3781:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4157:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4200:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4243:	snap := NewClusterSnapshot(e.Cluster.noder, e.Cluster.Hasher, e.Cluster.ReplicaN)
4517:	snap := NewClusterSnapshot(NewLocalNoder(e.Cluster.Nodes()), e.Cluster.Hasher, e.Cluster.ReplicaN)

holder.go
1465:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1668:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1889:	snap := NewClusterSnapshot(s.Cluster.noder, s.Cluster.Hasher, s.Cluster.ReplicaN)
1963:	snap := NewClusterSnapshot(c.Cluster.noder, c.Cluster.Hasher, c.Cluster.ReplicaN)
2021-01-06 22:53:20 -06:00
Travis
3f26d667b4
remove pilosa.DefaultPartitionN 2021-01-06 22:45:44 -06:00
jaten-molecula
a6bf52d753
Merge pull request #1290 from travisturner/disco-subpackages
add subpackages: topology, net
2021-01-06 17:23:56 -06:00
Jason E. Aten
6a845f1de1 use bbolt v1.3.5 that has fixed the checkptr bugs 2021-01-06 23:19:53 +00:00
Travis
20816ffa20
remove pilosa.URI 2021-01-06 16:19:14 -06:00
Travis
4515a24e48
change all references to use subpackages: topology, net 2021-01-06 16:09:24 -06:00
Maxton Huff
d10e45648b change f.path to f.path() 2021-01-06 15:58:01 -06:00
Travis
f8e6115c0e
fix linter and go.mod issues 2021-01-06 15:01:50 -06:00
Travis
2c1a019c9e
add licence headers 2021-01-06 14:42:28 -06:00
Travis
bd989f464a
change bbolt version back to 1.3.3 2021-01-06 13:26:35 -06:00
Travis
0da35fb72b
add subpackages: topology, net 2021-01-06 13:21:36 -06:00
Matthew Jaffee
d6cba17a01
Merge pull request #1274 from jaffee/generalized-groupby-sort-2
Add ability to sort on count or aggregate in GroupBy. Fix bug with offset being unsupported. Fix bugs with limit interacting poorly with other arguments.
2021-01-05 09:41:18 -07:00
Matt Jaffee
216e28a77e
add getSorter tests, fix bugs 2021-01-05 09:54:46 -06:00
Matt Jaffee
6dccb3d6be
remove (unused) sorting code related to fields, add comments 2021-01-03 08:34:53 -06:00
Matt Jaffee
6094663e7a
fix bug with "having" and "limit" in GroupBy
the limit could get applied before "having" in some cases which could
result in results being discarded which met the having condition while
results were kept which did not, ultimately resulting in GroupBy
falsely reporting fewer results than actually existed.
2021-01-01 21:56:59 -06:00
Matt Jaffee
ea539d8241
simplify groupby sorting and fix bugs
Back out support for sorting on fields (only count and aggregate
supported for now).

Fix bug where default return of "true" caused sort to be unstable. (If
they are equal, Less should return false)

Fix bug where limit was being applied before sorting.

Fix bug where offset was not actually allowed to be an argument to
GroupBy (weird! guess we weren't testing that very well)

Apply "having" after calculating Count(Distinct) aggregate so that
having can apply to that.

Switch to stable sort to make testing easier.
2020-12-31 14:42:03 -06:00
Matt Jaffee
5fdae74812
draft of sorting groupby results 2020-12-31 14:41:52 -06:00
Matthew Jaffee
46bbff786e
Merge pull request #1245 from codysoyland/groupby-aggregate-distinct
Add Distinct call as GroupBy aggregate
2020-12-30 10:05:37 -07:00
Matt Jaffee
16fd6a7edd
add tests for GroupBy(Distinct), fix various problems
We execute the aggregate Distinct calls after the GroupBy is complete,
and we need these to act like non-remote calls in that they forward to
all nodes, but like remote calls in that they bypass key
translation. Added a "PreTranslated" flag to the QueryRequest to
achieve this.

Discovered an issue where a nil *Row in EmbeddedData would cause a
panic in the protobuf serialization. Changed the encoding code we
control to never pass a nil *Row.

Got fed up with lack of context on errors and added wrapping to all
calls under executor.executeCall as well as a few other places.

Handled a situation where not having data on a shard for a particular
field could cause a query to error instead of just treating that
fragment as being empty. (see the switch in executeDistinctShardSet)

Stopped GroupBy from executing the Count(Distinct) aggregate on Remote
calls.

Fixed a longstanding issue where errors retrieved from remote query
calls had a garbage character at the front due to treating a protobuf
payload as an error message instead of decoding it. (see
http/client.go)
2020-12-30 08:13:41 -06:00
Cody Soyland
fd7417a49b
Use shardwidth instead of hardcoded value 2020-12-30 08:12:09 -06:00
Cody Soyland
f099a90264
Modify aggregate distinct logic and add tests
Use execute instead of directly using executeCount
Address code review feedback (add additional filters if provided)
Add basic tests
2020-12-30 08:12:09 -06:00
Cody Soyland
b435e9d793
Add Distinct call as GroupBy aggregate 2020-12-30 08:12:08 -06:00
Matthew Jaffee
fd3a423342
Merge pull request #1248 from jaffee/make-tests-more-robust
fix test failures in case of running Pilosa on system
2020-12-29 15:46:19 -07:00
Matt Jaffee
bed2cffd5e
fix test failures in case of running Pilosa on system
If you're running a Pilosa with mostly default configuration on your
system, some of these tests would fail due to things like port
conflicts. These changes address the most common failures.
2020-12-29 13:57:18 -06:00
Cody Soyland
1fa2a65c0b
Test to demonstrate failure running Distinct 2020-12-28 16:50:06 -06:00
Matthew Jaffee
4447d6fa76
Merge pull request #1261 from jaffee/some-distinct-bugs
fix Count(Distinct) bug and add better tests
2020-12-28 15:24:50 -07:00
Matt Jaffee
1ed91ebad3
simplify error messages
also remove test which was accidentally committed
2020-12-28 16:06:40 -06:00
Matt Jaffee
790bea147f
make view and fragment not found errors constant
based on code review feedback
2020-12-28 15:59:49 -06:00
Matt Jaffee
a3b07ff519
re-add log line which has more utility than I thought
From Nia:
While debugging the Q2 bugs this was somewhat useful in analyzing cluster events. As for the spammy part. . . that seems to be more of an issue with spamming our resets than an issue with the log itself.
2020-12-28 15:30:38 -06:00
Matt Jaffee
21c67352af
remove paranoia mode in top level Pilosa 2020-12-28 15:25:13 -06:00
Matt Jaffee
757c8a86b5
add comments, simplify tests, move ToCSV code
generally, address code review feedback
2020-12-28 15:22:31 -06:00
Matt Jaffee
27ca9dab36
don't hide error getting sign bitmap 2020-12-28 11:14:04 -06:00
Matt Jaffee
446950979a
fix potential nil dereference in SignedRow.ToRows
This used to be possible to hit, but I think now that Distinct on a
set field returns a *Row rather than a SignedRow it isn't an issue. (I
wasn't able to trigger it in the tests). Adding the fix anyway as it
seems safer than not.

The rest of the changes are test infrastructure to make it easy to
call GRPC queries and verify the results as CSV.
2020-12-28 11:00:46 -06:00
Matt Jaffee
1372bafe02
fix bugs where row index and field weren't always being propagated
I used a "paranoia" check to find these, but then realized the check
had a ton of false positives and doing it properly wasn't going to be
straightforward. I'm leaving the paranoia stuff in unless there are
objections, because I've wanted it before and not had it.

I also removed a log line that is very verbose and I don't think helps
anyone.
2020-12-23 19:08:10 -06:00
Matt Jaffee
427e9cb538
fix executor tests which were expecting a signedrow from Distinct 2020-12-23 15:33:15 -06:00
Matt Jaffee
6ff6fa7bb8
fix comments/capitalization 2020-12-23 14:44:18 -06:00
Matt Jaffee
9ee5f52a11
fix some Distinct key translation issues (e.g. empty index)
This commit changes executeDistinct to return either a *Row or a
SignedRow (instead of only being able to return a SignedRow). Distinct
on a set field will return a *Row while an int field will still return
a signed row.

We then add Field and Index fields to the Row object so that we can
determine how to translate the rows IDs to keys (if needed). This adds
a lot of logic around the translation which fixes bugs where Distinct
calls would fail to get translated.

There are, I think, still issues if you were to try to join a keyed
field to a keyed index which wasn't explicitly specified as the
field's foreign index. The IDs in the field wouldn't be using the same
translation as the IDs in the index, so the query might appear to work
but give incorrect results.
2020-12-23 14:37:03 -06:00
Matt Jaffee
385381e5f3
fix issue where a shard with no data can cause query to fail
add Distinct test with integer data, and because one of the records
had a null value (and was in a shard by itself), it uncovered this
issue. I added a special error type if a view or fragment is not found
when so that we can match against it and ignore it when calculating
the results for a query.

I also added an implementation within executeCount to handle the
SignedRow case, but discovered that handlePrecalls always dumps the
negative data and that will be a bigger thing to fix
2020-12-23 14:37:03 -06:00
Matt Jaffee
121f3fb610
fix Count(Distinct) bug and add better tests
the Distinct call would get precomputed correctly, but then the
executeCount would happen in the available shards context of the
index. So if the index only had records in (e.g.) shards 10,12,18,22,
and all the values of the Distinct call were in shard 0, you'd see 0
results.

The fix skips the whole map/reduce step of executeCount (which was
basically fake anyway when the argument is precomputed), and just adds
up all counts of all the precomputed segments.

This currently won't properly count Distinct values from an int field
which contains negative numbers... going to add a test and fix for
that next.

There is also still a key translation bug which is why the one test
case is commented out... fix coming for that soon as well.
2020-12-23 14:37:03 -06:00
Ben Johnson
fc7f7d6a7c
Merge pull request #1260 from molecula/bench-1month 2020-12-22 09:42:55 -07:00
Ben Johnson
02c4c1dff4
Merge branch 'master' into bench-1month 2020-12-22 08:51:18 -07:00
Ben Johnson
c189cb8e81
Merge pull request #1259 from molecula/bench-chmod-x
Make scripts/bench.sh executable
2020-12-22 08:51:03 -07:00
Ben Johnson
64f2ff6b78 Change benchmark script to test against GH 1 month of data 2020-12-22 08:10:29 -07:00
Ben Johnson
34c46cf084 Make scripts/bench.sh executable 2020-12-22 07:44:43 -07:00
tgruben
4b36805190
Merge pull request #1254 from jaten-molecula/migration_speedup
smaller batches of write Tx help boost migration speed
2020-12-21 13:28:31 -06:00
Jason E. Aten
1efff0c99b smaller batches of write Tx help boost migration speed 2020-12-21 19:00:13 +00:00
tgruben
e290e13d0b
Merge pull request #1252 from jaten-molecula/minimal_view_opening
pilosa: only open views with data
2020-12-18 18:41:44 -06:00
jaten-molecula
264f4382d5
Merge branch 'master' into minimal_view_opening 2020-12-18 18:19:24 -06:00
Ben Johnson
2d35f0d96a
Merge pull request #1243 from molecula/nightly-benchmark
Add nightly benchmark script.
2020-12-18 17:18:36 -07:00
jaten-molecula
94c38a59af
Merge branch 'master' into nightly-benchmark 2020-12-18 18:09:35 -06:00
Jason E. Aten
035073555a pilosa: only open views with data
- Previously, on timequantum schemas, we would
create and open a view for the cartesian
product of every possible view and shard.

- This caused us to be very slow on re-open,
and to use lots of memory for views that
held nothing.

- This change makes startup faster, memory
use much lower, and should speed migration.
2020-12-19 00:03:31 +00:00
Matthew Jaffee
7b6c6303ce
Merge pull request #1246 from jaffee/1242-createdAtBug
Fix field "createdAt" race by sending schema changes to coordinator
2020-12-18 12:06:29 -07:00
Ben Johnson
d635ece5a9 Add workflow name to benchmark 2020-12-18 09:33:50 -07:00
Matt Jaffee
b8cbd54d1b
forward all CreateIndex/CreateField requests to coordinator
this should avoid a race condition with CreateField where createdAt
can get out of sync if there are multiple concurrent requests.

The client methods didn't allow specification of the URI, so I
modified the implementation to find the coordinator and send to it
explicitly.
2020-12-18 10:16:46 -06:00
Matt Jaffee
58b9418f3c
add failing test for field creation race 2020-12-17 16:30:23 -06:00
Ben Johnson
cfdc7f4c63 Add nightly benchmark script.
This commit adds a script for executing a nightly benchmark and posting
the results to Slack.
2020-12-17 09:23:40 -07:00
jaten-molecula
513743f30d
Merge pull request #1241 from jaten-molecula/tests_for_NewBitmapBitmapFilter
add tests for NewBitmapBitmapFilter constructor
2020-12-16 21:39:18 -06:00
Jason E. Aten
0db4914bc4 add tests for NewBitmapBitmapFilter constructor
- document sort.Stable need
2020-12-17 00:27:34 +00:00
seebs
ad35f11a27
Merge pull request #1208 from seebs/fastRows2
Performance improvements for transactional backends scanning fragments
2020-12-16 17:14:54 -06:00
jaten-molecula
5b43513063
Merge branch 'master' into fastRows2 2020-12-16 17:09:46 -06:00
Seebs
cc5e822799 fix comment, remove unneeded step
It turns out NewSliceBitmap can take an initial set of values
already.
2020-12-16 17:00:34 -06:00
Nia
26ab79ecb8
Merge pull request #1238 from niaow/fix-snapshot-queue
Fix automatic snapshot queue enable check
2020-12-16 17:01:09 -05:00
jaten-molecula
6263f0bcfd
Merge branch 'master' into fix-snapshot-queue 2020-12-16 13:45:04 -06:00
Seebs
4ddbadcea7 review issues: fix unclearSets (now sliceDifference) and prune/fullPrune
unclearSets was completely broken and I have no idea why the test I thought
was testing it didn't actually catch that problem. Added unit tests and fixed
the logic. Improved/clarified prune and fullPrune, and unexported their
names because why export methods on an unexported type.

Also improve some comments and rename a variable or two to improve clarity.
2020-12-16 13:18:18 -06:00
Seebs
0952db5af7 Add (temporary, perhaps) locking on TestTx_CountRange
On roaring, CountRange needs to have exclusive access to a fragment, but
doesn't currently require a lock, because it's usually used from inside
other already-locked things.
2020-12-16 13:18:18 -06:00
Seebs
de14762661 create Tx tests for CountRange
CountRange for RBF had a subtle bug which wasn't noticed, so, let's
have some CountRange testing and also a benchmark.

We also fix a couple of subtle bugs caught in the process of developing
and testing this.

SliceContainers will allow nil containers, but doesn't return them when
iterating because there's various things that can panic if called on a nil
container. Since countEmptyContainers() has to traverse the whole bitmap
anyway, it doesn't matter which it counts, so we replace it with
countNonEmptyContainers(), and adjust test cases accordingly. This fixes
an issue where if roaring is smart enough to insert a nil container
into a SliceContainers, trying to write it to a file produces an invalid
bitmap with offsets off by 16 and one container fewer than its header predicts.

RBF: don't try to count 0 bits in a container

If we're to the "last container", and we'd be counting all the bits less than
zero, we can skip that. This avoids hitting a bug, which is that c.countRange
doesn't handle BitmapPtr.
2020-12-16 13:16:46 -06:00
Seebs
17c24c236a don't try to use the rowCache for CountRange
Several issues:
1. tx.frag could be non-nil but not the fragment requested.
2. start and end need not be exact row boundaries.
3. therefore this could be returning the count of the row containing
"start", for a fragment other than the one requested.
4. also in fact the rowcache wasn't populated before this so in one
memory profile, this function alone was responsible for nearly
100GB of cached values...
2020-12-16 13:16:46 -06:00
Seebs
dec0a00155 add container N to ConsiderKey 2020-12-16 13:16:46 -06:00
Seebs
23e16474ae use ApplyFilter instead of roaring.ApplyFilterToIterator
In some cases, ApplyFilter can be significantly faster. On the other hand, it doesn't
matter as much as you might think on the mutex imports, because we've already sucked
most of the time out of those.
2020-12-16 13:16:46 -06:00
Seebs
e4e94a5668 prevent weird rare failures in mutex imports
Added additional mutex sample data and batches of it so we can
confirm that overwrite works. It didn't work, so that needed to be fixed.

Couple of things:
(1) Wasn't updating "last value seen" so the check for an unsorted list
didn't work.
(2) Also didn't handle the case where there were to-clear values higher
than any to-set value.

This could result in bits not getting cleared, which could result in
there being more than N bits to clear for N new bits. And that could cause
really strange problems when the input slices were parts of a single
larger slice, because bit positions to clear could get shoved in as
possible columns in a future batch.
2020-12-16 13:16:46 -06:00
Seebs
e99744c8da Do benchmarks with read-only Tx after committing write sometimes
For the Rows benchmark, we were continuing to use the original writable
transaction, meaning RBF was spending all its time looking up dirty
pages in the transaction's dirty page cache rather than working with
the disk in any way. It wasn't clear whether this was hurting or
helping performance, but it was clear that it wasn't testing the
"real" workload use case, where queries are done against the RBF
file rather than the dirty page cache.

Modify the benchmark to test it both ways for comparison. Answer:
The RBF file is faster than the in-memory map (!).
2020-12-16 13:16:46 -06:00
Seebs
9b13ab7dd3 use readLeafCellKey to read a leaf cell's key 2020-12-16 13:16:46 -06:00
Seebs
dc67149326 read leaf cells through a pointer
This reduces noticably the cost of reading leaf cells, by passing
a single pointer down the stack instead of the entire data structure
up the stack. It's only a few percent overall, but it's noticeable.
2020-12-16 13:16:46 -06:00
Seebs
7c415b4217 Implement rbf-specific ApplyFilter
This gives RBF an ApplyFilter that can run without instantiating containers
when the filter it's using doesn't need them instantiated. We can also seek
ahead in cases where we know the next key we care about is not just the next
key numerically.
2020-12-16 13:16:46 -06:00
Seebs
2c4aff2d18 add benchmarks for f.rows()
This is a simplistic benchmark for f.rows() to let us evaluate its performance
in preparation for trying to do some profiling and tuning.
2020-12-16 13:16:46 -06:00
Seebs
30d5f891c0 create naive ApplyFilter 2020-12-16 13:16:46 -06:00
Seebs
59d89dda99 Allow arbitrary and potentially more efficient filtering of bitmaps
This is a partial solution to a nasty performance problem, which is that
a ContainerIterator has to *generate* all the containers. With roaring, this
was cheap because they already exist in memory; with transactional backends,
it's an allocation per container, *even for the containers we don't use*.

This design admits filters which can distinguish between answers they
can give just based on keys and times when they actually need containers
instantiated, and can also give hints as to future answers -- saying "yes"
or "no" to entire rows at a time, or indicating when they're done.

This is only part of the solution; we also need a Tx API hook for
doing scans like this which doesn't rely on ContainerIterator.
2020-12-16 13:16:46 -06:00
jaten-molecula
440b90f3c8
Merge pull request #1240 from jaten-molecula/roaring_printutil
roaring: print utility AsContainerMatrixString for diagnostics
2020-12-16 13:02:47 -06:00
Jason E. Aten
1a6f573739 roaring: print utility AsContainerMatrixString for diagnostics
AsContainerMatrixString returns a string showing
 the matrix of rows in a shard, showing the count of hot (1) bits
 in each container.
2020-12-16 18:50:45 +00:00
Nia Weiss
eab70e2314
use the txf to determine if snapshots are needed 2020-12-16 11:00:27 -05:00
Nia Weiss
aaf94c6aeb
fix the automatic snapshot queue enable check
The "needs snapshot queue" check was broken, as it only checked inside a loop over indices.
If there are no indexes yet (or more likely if the indices have not yet been loaded off of disk), then this would never use the snapshot queue on roaring.
2020-12-16 08:15:17 -05:00
Cody Soyland
87bf0df786
Merge pull request #1234 from codysoyland/rbf-usage-calc
Fix disk usage calculation in RBF backend
2020-12-15 15:57:17 -06:00
Cody Soyland
4cb21da6e9 Fix disk usage calculation in RBF backend 2020-12-15 13:39:27 -06:00
Cody Soyland
765bac992d
Merge pull request #1225 from codysoyland/upgrade-gopsutil
Upgrade gopsutil
2020-12-14 11:36:07 -06:00
Cody Soyland
5eb726ce59 Upgrade gopsutil 2020-12-14 10:58:28 -06:00
tgruben
3beaed1645
Merge pull request #1220 from jaten-molecula/avoid_dynamic_dispatch
FragSpec as struct, fragment fields to avoid dynamic dispatch
2020-12-14 09:21:57 -06:00
Jason E. Aten
b254c6776b FragSpec as struct, fragment fields to avoid dynamic dispatch
- allow inlining of getters index(), view().
 - GOMAXPROCS set to 128
2020-12-12 16:39:24 +00:00
tgruben
b0755577b3
Merge pull request #1218 from jaten-molecula/short_txkey
short_txkey elides index and shard from the txkey
2020-12-11 17:30:40 -06:00
Jason E. Aten
b52a814b3c short_txkey elides index and shard from the txkey
- use short_txkey for rbf
 - short_txkey breaks a bunch of bolt_test.go, so leave it on (long) txkey for now.
 - remove SliceOfShards method from Tx interface
2020-12-11 22:24:56 +00:00
tgruben
c5302f2f57
Merge pull request #1212 from tgruben/fragment-refactor
Fragment refactor (wip)
2020-12-11 15:08:19 -06:00
Todd Gruben
8ad7afbe43 FragProxy reduces string memory consumption drastically
for datasets with lots of views, because we don't
replicate path, index, field, view strings so often.
2020-12-11 21:01:15 +00:00
jaten-molecula
30502c99ab
Merge pull request #1214 from jaten-molecula/readwrite_locks
use tx.mu.RLock for OffsetRange, Lock for AddRoaring
2020-12-11 08:13:52 -06:00
Jason E. Aten
2b569b1edf use tx.mu.RLock for OffsetRange, Lock for AddRoaring 2020-12-11 13:53:27 +00:00
tgruben
f5e656138f
Merge pull request #1211 from jaten-molecula/skip_serz_1node
avoid serializing for sync shards in 1 node cluster situation
2020-12-10 17:16:10 -06:00
Jason E. Aten
7571792401 avoid serializing for sync shards in 1 node cluster situation 2020-12-10 20:54:32 +00:00
Maxton Huff
8c20255b12
Merge pull request #1210 from Maxtonian/lonquerytime2
deprecate cluster.long-query-time and create long-query-time
2020-12-10 11:14:09 -06:00
Maxton Huff
dee700741a deprecate cluster.long-query-time and create long-query-time
moved lonquerytime from cluster into server and moved cluster.longquerytime into top level config
kept cluster.longquerytime for backwards compatibility, favored if both longquerytime options are present
2020-12-10 10:51:31 -06:00
tgruben
087418566b
Merge pull request #1204 from jaten-molecula/clear_cursors
reset cursor stacks before reuse
2020-12-09 19:01:08 -06:00
jaten-molecula
21cb390d2f
Merge branch 'master' into clear_cursors 2020-12-09 17:01:21 -06:00
Jason E. Aten
81b9586a4b reset cursor stacks before reuse 2020-12-09 21:41:41 +00:00
Cody Soyland
1990ecf2b6
Merge pull request #1205 from codysoyland/docker-build-make
Use "make" inside docker build so that CGO_ENABLED uses exported value from Makefile
2020-12-09 15:02:04 -06:00
Cody Soyland
f351b7efa6 Use "make" inside docker build so that CGO_ENABLED uses exported value from Makefile 2020-12-09 13:21:07 -06:00
Cody Soyland
1add244f8a
Merge pull request #1201 from codysoyland/default-roaring
Default TxSrc to roaring
2020-12-09 09:36:28 -06:00
Cody Soyland
c1fe8b214a Default TxSrc to roaring 2020-12-09 09:31:40 -06:00
Cody Soyland
53f6a127af
Merge pull request #1198 from codysoyland/docker-build-test
Disable cgo on all builds, add additional tests for docker
2020-12-09 09:17:03 -06:00
Cody Soyland
5d18c0af2b Enable cgo on test -race 2020-12-09 09:00:03 -06:00
Cody Soyland
bc94c7bcdf Remove lmdb dependency and references, vendor Barrier 2020-12-09 08:43:23 -06:00
Cody Soyland
eef6359db3 Disable cgo on all builds, add additional tests for docker 2020-12-08 19:42:51 -06:00
tgruben
d05531b77a
Merge pull request #1197 from jaten-molecula/rowcache_off_by_default
rowcache off by default. pilosa server --rowcache-on turns it back on.
2020-12-08 19:32:19 -06:00
Jason E. Aten
03a54c6d5f rowcache off by default. pilosa server --rowcache-on turns it back on. 2020-12-08 23:18:45 +00:00
tgruben
d4d30e160b
Merge pull request #1196 from jaten-molecula/diagn
pilosa debugstats and rbf tooling for enhanced debugging/diagnostics
2020-12-08 16:58:54 -06:00
Jason E. Aten
82d07bc123 debugstats and rbf tooling for enhanced debugging/diagnostics 2020-12-08 22:47:40 +00:00
tgruben
9f7fa7eaad
Merge pull request #1195 from jaten-molecula/rbf_doc
document pattern of branch splits
2020-12-08 16:19:56 -06:00
tgruben
63d67ac65e
Merge branch 'master' into rbf_doc 2020-12-08 15:52:46 -06:00
tgruben
662073c284
Merge pull request #1194 from jaten-molecula/fix_freepageset
fix bug in pgno computation in freePageSet
2020-12-08 15:52:25 -06:00
Jason E. Aten
cbff5bd29d document pattern of branch splits 2020-12-08 20:50:29 +00:00
Jason E. Aten
96abbfa059 fix bug in pgno computation in freePageSet 2020-12-08 20:45:54 +00:00
Cody Soyland
bd060b6fd2
Merge pull request #1191 from codysoyland/docker-disable-cgo
Dockerfile: switch back to alpine and disable cgo
2020-12-07 10:07:56 -06:00
Cody Soyland
2bd27cdf5e Upgrade alpine and disable cgo 2020-12-07 09:26:52 -06:00
Cody Soyland
5d08d54518 Revert "ubuntu 20:10 image instead of alpine, for cgo support"
This reverts commit ef156f6172.
2020-12-07 09:26:52 -06:00
Nia
8a6d20d314
Merge pull request #1168 from niaow/pilosa-id-gen
Add ID auto-generation on the coordinator
2020-12-07 09:58:13 -05:00
Nia
a4f538ffec
Merge branch 'master' into pilosa-id-gen 2020-12-07 09:46:58 -05:00
Nia
2a863e5c13
clarify OptServerOpenIDAllocator
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2020-12-07 08:08:51 -05:00
jaten-molecula
d38184a5ff
Merge pull request #1183 from jaten-molecula/rm_lmdb
remove lmdb as tx backend
2020-12-04 17:32:15 -06:00
Jason E. Aten
7a9e0969cb remove lmdb as a Tx backend
- test only still uses a Barrier utility from the go-lmdb package;
  it could be ported in at some point.
2020-12-04 23:17:59 +00:00
Cody Soyland
4f14774883
Merge pull request #1174 from codysoyland/query-timing
Add query duration to gRPC responses
2020-12-04 15:47:03 -06:00
Cody Soyland
fc3b64e500 Add table conversion to duration timing 2020-12-04 15:19:12 -06:00
Cody Soyland
c33eafc27e Add tests for streaming queries 2020-12-04 15:19:12 -06:00
Cody Soyland
6830657d12 Add query duration to gRPC responses
This adds a "duration" parameter to RowResponse and TableResponse, which
will be populated with the query duration in nanoseconds.

For QueryPQLUnary and QuerySQLUnary, the duration is a included in the
returned TableResponse.

For QuerySQL and QueryPQL, only the first RowResponse in the stream will
contain the duration.
2020-12-04 15:19:12 -06:00
Ben Johnson
26789ef0b5
Merge pull request #1163 from molecula/page-pool
Add sync.Pool for RBF pages
2020-12-04 08:08:11 -07:00
Nia Weiss
7ea2e4b7e3
add ID auto-generation on the coordinator 2020-12-03 13:04:14 -05:00
Ben Johnson
79e6156003 Add sync.Pool for RBF pages 2020-12-03 07:32:36 -07:00
Ben Johnson
1ce15a51c9
Merge pull request #1157 from molecula/put-leaf-cell-faster 2020-12-01 15:49:16 -07:00
jaten-molecula
836540151b
Merge branch 'master' into put-leaf-cell-faster 2020-12-01 16:24:09 -06:00
tgruben
dd856378d1
Merge pull request #1156 from jaten-molecula/container_key_span
RoaringIterator.ContainerKeySpan method
2020-12-01 16:22:57 -06:00
Ben Johnson
df958f40dd Optimize putLeafCellFast() 2020-12-01 12:12:54 -07:00
jaten-molecula
53b64bd939
Merge branch 'master' into container_key_span 2020-12-01 09:15:11 -06:00
Matthew Jaffee
c8c7b98654
Merge pull request #1142 from alanbernstein/update-ui-paths
Maintain list of frontend routes, update 'vds' to 'tables'
2020-12-01 07:42:50 -07:00
Jason E. Aten
6f4ca78bc4 RoaringIterator.ContainerKeySpan method
- enables rbf ingest optimization. When we know there won't be
   updates involved we can bulk import faster.
2020-12-01 01:52:58 +00:00
Alan Bernstein
4dc38bee02 Maintain list of frontend routes, updates 'vds' to 'tables' 2020-11-25 13:30:28 -06:00
Nia
df13c72351
Merge pull request #1145 from niaow/err-id-on-keyed
Report an error when an ID is used on a keyed field
2020-11-25 13:48:04 -05:00
Nia Weiss
353fd3937d
report an error when an ID is used on a keyed field 2020-11-25 11:37:18 -05:00
Alan Bernstein
9e3e0a6be7
Merge pull request #1013 from alanbernstein/query-activity-api
Add query history endpoint
2020-11-24 08:46:43 -06:00
Alan Bernstein
65877c1e56 Store start instead of age, skip remote, fix timing bug 2020-11-23 21:31:40 -06:00
Alan Bernstein
0c8e4afe45 Set test nodeIDs to guarantee iteration order in executor 2020-11-23 20:23:28 -06:00
Alan Bernstein
a8a7e53382 Add query-history test 2020-11-23 20:23:28 -06:00
Alan Bernstein
c5a7a259aa Make minor fixes to query tracker 2020-11-23 20:23:28 -06:00
Alan Bernstein
2bc2a32263 Make query history length configurable 2020-11-23 20:23:27 -06:00
Alan Bernstein
b172f4d05b Include index in query history response 2020-11-23 20:23:27 -06:00
Alan Bernstein
542a6ffdb6 Gather query history from remote nodes 2020-11-23 20:23:27 -06:00
Alan Bernstein
bbd147d18f Replace query history map with ringBuffer 2020-11-23 20:23:27 -06:00
Alan Bernstein
65de5df2a9 Update tracker test 2020-11-23 20:23:27 -06:00
Alan Bernstein
c94d242097 Add basic implementation of query history endpoint 2020-11-23 20:23:27 -06:00
seebs
55d0c12703
Merge pull request #1131 from seebs/randomerQuery
Improve random-query
2020-11-23 11:58:53 -06:00
Seebs
3d802f428b add Distinct, be more consistent about using correct rand.Rand
The RandomQueryConfig has its own seeded RNG, but we didn't always use
it (especially in the last two commits, but also I think in one previous
thing), so let's use it more consistently.

We check for int fields (as opposed to decimal), and if we find them,
we add Distinct to our list of potential queries to use if and only
if we've got a depth of at least one so there'd be a child query under
the current query, and if we do, grab one of the int (not decimal)
fields and do a query on that.
2020-11-23 09:54:59 -06:00
Seebs
796d646a0c handle integer fields
Extend field handling to include int (and decimal) fields, allowing them
to have range operations specified on them.
2020-11-23 09:51:29 -06:00
Seebs
2a2a8abbd4 support time fields
For time fields, allow specifying a range of times, then 19/20 times,
specify "from" and "to" times in that range when querying those fields,
rather than just looking at the standard view all the time.
2020-11-23 09:51:29 -06:00
Seebs
48b97d6ad4 report QPS after last query
More generally, report QPS not at 0 queries, which is boring, but every
100 queries *and* after the last query if the last query wasn't at a
multiple of 100 queries. Makes the output slightly more useful, I think.
2020-11-23 09:51:29 -06:00
Matthew Jaffee
7271fbf396
Merge pull request #1015 from alanbernstein/dont-create-keys-directory
Check index.keys before opening translate store to avoid unnecessary keys directory
2020-11-20 14:30:37 -07:00
Matt Jaffee
a48bf28be2
don't try to translate keys on unkeyed indexes
this causes a few things to error earlier than they otherwise would
have, hence the changed tests.
2020-11-20 14:48:28 -06:00
Alan Bernstein
063a3b96e3
Check index.keys before opening translate store 2020-11-20 12:43:15 -06:00
Nia
106952dc5e
Merge pull request #1106 from niaow/topk-time
TopK on time
2020-11-20 13:24:05 -05:00
Nia
c8ab2a9fb3
Merge branch 'master' into topk-time 2020-11-20 13:11:51 -05:00
Nia Weiss
d7b9568960
add licesnse header to bsi_test.go 2020-11-20 12:40:28 -05:00
Nia Weiss
410a372351
clarify bsi-building preconditions 2020-11-20 12:38:53 -05:00
Nia Weiss
f9c196e418
skip roaring add test in race
Otherwise it overloads the race detector.
2020-11-20 12:16:09 -05:00
tgruben
72f4024e99
Merge pull request #1122 from jaten-molecula/inlined_immutable_map_rb
rbf: use an inlined immutable.Map<uint32, int64> for the PageMap
2020-11-20 10:44:44 -06:00
Nia Weiss
5d2c42b7bf
address documentation todo in pivotDescending 2020-11-20 11:13:44 -05:00
Matthew Jaffee
64b83137a0
add tests for addBSI 2020-11-20 11:07:30 -05:00
Nia Weiss
46818863e8
implement TopK on time
This replaces the former TopK BSI building algorithm, as the row cache was too expensive.
Additionally, BSI addition has been optimized with specialized adders inside of roaring.
2020-11-20 11:06:55 -05:00
Jason E. Aten
e1bb6e303a rbf: use an inlined immutable.Map<uint32, int64> for the PageMap
- goes 7% faster on kitchen sink import test

- reduces total allocations by 5% on same test.
2020-11-20 00:49:41 +00:00
jaten-molecula
47202b0ed2
Merge pull request #1095 from molecula/fast-write
Implement optimized fast leaf write.
2020-11-19 16:04:31 -06:00
Ben Johnson
a9831ad5a1 Replace literals with leafCellHeaderSize 2020-11-19 14:18:53 -07:00
Ben Johnson
d125c68275 Fix estimated page size calculation to include index padding. 2020-11-19 14:12:43 -07:00
Ben Johnson
33334511c4
Merge branch 'master' into fast-write 2020-11-19 13:44:09 -07:00
jaten-molecula
5b8cda3c88
Merge pull request #1120 from molecula/fix-root-record-overflow
Fix rbf write root record iterator reset
2020-11-19 13:11:09 -06:00
Ben Johnson
a31487b873 Fix rbf write root record iterator reset 2020-11-19 11:15:24 -07:00
jaten-molecula
61bdc2257b
Merge pull request #1111 from jaten-molecula/sync_pool
rbf: reuse cursors with sync.Pool/arena
2020-11-19 11:17:20 -06:00
Jason E. Aten
9c7bc603af rbf: reuse cursors with sync.Pool or arena
- the sync.Pool default uses little memory under CI.

- arena approach provides ability to control the maximum memory
  used by rbf Cursors.

- cursor caching is adjustable with --rbf-cursor-cache
  currently 0 by default (meaning use sync.Pool), and
  larger than 0 meaning use an arena of this size.
  With the arena, 20 or less is needed to pass CI.

- rbf test suite runs ~ 4x faster

- kitchen sink ingest test runs 16% faster.

- report TotalAlloc in CALLSTATs

fixes #1105
2020-11-19 17:02:49 +00:00
jaten-molecula
274a95c4da
Merge pull request #1115 from molecula/remove-rbtree
Use immutable.SortedMap for root records
2020-11-19 11:00:57 -06:00
Ben Johnson
26d0e9d958
Merge branch 'master' into remove-rbtree 2020-11-19 07:27:09 -07:00
tgruben
b849fe4b98
Merge pull request #1116 from jaten-molecula/pilosa_txsrc
use pilosa server --txsrc instead of --tx to prevent viper env var shadowing
2020-11-18 14:37:10 -06:00
Jason E. Aten
524c78623f repair pilosa/ctl/server_test too 2020-11-18 18:53:22 +00:00
Ben Johnson
0175c66756 Use immutable.SortedMap for root records
This commit fixes a bug where the root record cache was being
updated in-place causing a race condition with other transactions
using it. The cache implementation has been changed from `rbtree`
to an `immutable.SortedMap`.
2020-11-18 11:22:52 -07:00
Jason E. Aten
06eb3afaaa use pilosa server --txsrc to prevent viper env var shadowing from stopping PILOSA_TXSRC getting through 2020-11-18 18:21:31 +00:00
jaten-molecula
a9c1ff3047
Merge pull request #1107 from jaten-molecula/fix_tx
restore the env variable PILOSA_TXSRC's affect
2020-11-16 17:26:22 -06:00
Jason E. Aten
744827d5cc restore the env variable PILOSA_TXSRC's affect 2020-11-16 23:18:50 +00:00
Ben Johnson
89ae5ad4b7
Merge branch 'master' into fast-write 2020-11-16 09:10:01 -07:00
Ben Johnson
519dc5069d Implement optimized fast leaf write.
This commit adds an optimized implementation for `putLeafCell()` if
the insert/update will not cause the page to overflow.
2020-11-16 08:13:35 -07:00
Nia
6dfbbf91d6
Merge pull request #1098 from niaow/topn-v3
Add TopK with perpendicular BSI bitmaps
2020-11-16 08:39:50 -05:00
Nia Weiss
02498ce57a
add TopK with perpendicular BSI bitmaps 2020-11-13 18:31:55 -05:00
tgruben
43443d10ff
Merge pull request #1097 from jaten-molecula/bitmap_foreach
rbf: BitN needs int32 to hold its maximum value.
2020-11-13 17:12:19 -06:00
Jason E. Aten
4120024b10 rbf: BitN needs int32 to hold its maximum value.
- decrease ArrayMaxSize and RLEMaxSize by 1
  to make space
- add TestForEachRange, fix bugs found in ForEach,
  where the call f() logic was backwards.
2020-11-13 22:59:18 +00:00
tgruben
b2e9e3904a
Merge pull request #1094 from jaten-molecula/elem_rb
rbf: keep ElemN and BitN up to date.
2020-11-13 15:44:15 -06:00
Jason E. Aten
d46b603cd6 rbf: keep ElemN and BitN up to date.
- fix a bug in computing leafCell.BitN in a run after a bit Remove
- shrink bitmaps on remove
- util_test.go has Cursor.DebugSlowCheckAllPages to verify;
  used by cursor_test.go
2020-11-13 21:18:09 +00:00
Cody Soyland
dc0ac0ccd0
Merge pull request #1092 from codysoyland/ci-go-version-cve-2020-28362
Ci: Go version update for CVE-2020-28362
2020-11-13 11:48:16 -06:00
Cody Soyland
e53b74261b Update default Go version 2020-11-13 11:23:39 -06:00
Cody Soyland
a2f49b6a84 Fix yaml syntax, add requires section 2020-11-13 11:23:39 -06:00
Cody Soyland
dca606dea8 Add pilosa (binary build) to .gitignore 2020-11-13 11:23:39 -06:00
Cody Soyland
671250d273 Update Go version for CVE-2020-28362, use param matrix 2020-11-13 11:23:39 -06:00
tgruben
d15dc4204b
Merge pull request #1086 from jaten-molecula/rbtree_root_records
rbf: use a red-black tree to manage the root records list
2020-11-13 11:14:51 -06:00
Jason E. Aten
eae82b72c2 rbf: use a red-black tree to manage the root records list
- 40% faster on ingest_test when putting 10K roots/containers.
 - 15% fewer bytes allocated total
 - clarifying renames leafCell.N -> ElemN, allocate -> allocatePgno,
   deallocate -> freePgno
2020-11-13 16:49:26 +00:00
jaten-molecula
cb73c71e02
Merge pull request #1072 from molecula/uni-wal
Refactor RBF to use a single WAL file
2020-11-11 15:44:45 -06:00
jaten-molecula
563c70dc43
Merge branch 'master' into uni-wal 2020-11-11 15:27:15 -06:00
tgruben
b3d2704066
Merge pull request #1085 from jaten-molecula/uniq_dbnames
unique db names so parallel test runs don't collide
2020-11-11 14:26:04 -06:00
Jason E. Aten
fd9210b31c unique db names so parallel test runs don't collide 2020-11-11 20:04:02 +00:00
Ben Johnson
81a64c5902 Add RBF halting; remove time based checkpoint 2020-11-11 11:17:07 -07:00
Ben Johnson
9eba299d35 Restrict max RBF transaction size 2020-11-10 08:14:14 -07:00
Ben Johnson
78eb9e0711 Fix linter 2020-11-10 07:07:06 -07:00
Ben Johnson
52340212f6 Add RBF dirty page cache 2020-11-09 16:11:20 -07:00
Ben Johnson
8de1959938 Remove RBF exclusive/direct write. 2020-11-09 08:23:09 -07:00
Ben Johnson
3554048877 Refactor RBF to use a single WAL file 2020-11-09 08:03:22 -07:00
tgruben
e99f7f0fc3
Merge pull request #1074 from jaten-molecula/fsync_applies_to_all
apply --fsync flag to all tx backend
2020-11-06 12:34:28 -06:00
Jason E. Aten
a38d4fa46c apply --fsync flag to all tx backend
- rename from --rbf-fsync to --fsync, as it
   now effects bolt, lmdb too.
2020-11-06 18:11:02 +00:00
jaten-molecula
822c7482a5
Merge pull request #1071 from jaten-molecula/parallel_migration_rb
run migration in parallel
2020-11-05 14:09:31 -06:00
Jason E. Aten
7e22994a6d run migration in parallel
- migration can be slow. parallelize it.
2020-11-05 18:31:27 +00:00
tgruben
bc26de63b0
Merge pull request #1070 from jaten-molecula/slurp_profile_rbf_comments
rbf default. Add TODO comments, slurp -profile returns a cpu profile
2020-11-03 19:52:54 -06:00
Jason E. Aten
458095a707 rbf default. Add TODO comments, slurp -profile returns a cpu profile
- default Tx is once again RBF, changed from bolt.
- document the RBF code review comments that were not addressed
  before #1052 was merged, so they don't get lost.
- they should be easily addressed by replaying the entire WAL file
  rather than from the DB meta page 0 notion of the last WalID
- cleanup rbf/cfg/cfg.go stale comments, ensure default0 respected.
  1 msec checkpoint time, 1MB wal segment defaults.
- return a specific error, ErrNoMetaFound, from findNextWALMetaPage()
  rather than io.EOF, since there actually wasn't any file IO involved.
- add http handlers for /cpu-profile/start and /cpu-profile/stop
  in http/handler.go enable CPU profiling at specific time points
  during an ingest or other operation.
2020-11-04 01:36:17 +00:00
tgruben
a55cdad139
Merge pull request #1069 from jaten-molecula/faster_new_tx
take a mutex off the fast path of TxFactory.NewTx
2020-11-03 19:15:26 -06:00
Jason E. Aten
bf36f54b8d take a mutex off the fast path of TxFactory.NewTx 2020-11-04 01:04:04 +00:00
tgruben
40a773b839
Merge pull request #1068 from jaten-molecula/qcx_gettx_error
qcx.GetTx returns an error
2020-11-03 18:34:24 -06:00
Jason E. Aten
6aadd13095 qcx.GetTx returns an error
- to indicate that the query context is already
   done.
 - handles the case where the import worker is
   interrupted early by a ctx cancellation,
   thus avoiding a panic.
2020-11-04 00:01:02 +00:00
Ben Johnson
06cb04f87a
Merge pull request #1052 from molecula/fix-wal-not-found
Fix RBF WAL ID panic.
2020-11-03 11:16:33 -07:00
Ben Johnson
731a1ef25e Refactor RBF WAL to only only checkpoint-in-full. 2020-11-03 10:41:31 -07:00
Ben Johnson
ea3732fa62 Fix WAL ID not found panic.
This commit changes the checkpointing to determine a minimum WAL ID
for readers and a max ID based on the writer. Pages are checkpointed
from the WAL up to the writer's max WAL ID but segments are removed
only up to the reader's minimum WAL ID. This ensures that WAL pages
are not removed out from under current read transactions.
2020-11-03 10:41:31 -07:00
Ben Johnson
c47b49a06e
Merge pull request #1053 from molecula/increase-rbf-wal-write-cache 2020-11-03 07:37:05 -07:00
Ben Johnson
db74f0dffa Increase RBF WAL write cache size to 1MB.
Previously we dropped the cache size to 64KB but that seems much
too low. Write performance suffers considerably.
2020-10-30 17:09:33 -06:00
Matthew Jaffee
3ff85ccb53
Merge pull request #1051 from molecula/default-txn-bolt-fix-ci
default to Bolt txn due to CI failures blocking other team
2020-10-30 15:01:57 -05:00
Matt Jaffee
83dd8026d5
default to Bolt txn due to CI failures blocking other team
Our nightly CI has been failing for a week due to WAL issues and it's
making it difficult for Kuba and Antonio to do things on the
integration repo. Hoping bolt backend will solve that in the short
term. I think the issue is Pilosa #1046 (that's from memory though)
2020-10-30 13:55:36 -05:00
Ben Johnson
bb5153a7c1
Merge pull request #1049 from molecula/rbf-cli-help
Improve RBF CLI help
2020-10-30 08:38:14 -06:00
Ben Johnson
d5369a084e Improve RBF CLI help 2020-10-30 07:25:36 -06:00
tgruben
f446eee088
Merge pull request #1048 from jaten-molecula/delete_empty
DeleteEmptyContainer true by default now
2020-10-30 06:30:09 -05:00
Jason E. Aten
9c66cd5a81 DeleteEmptyContainer true by default now 2020-10-30 04:15:53 +00:00
tgruben
4113a3d85b
Merge pull request #933 from molecula/qcx_no_auto_reset
pilosa: no automatic reuse of Qcx
2020-10-29 20:03:42 -05:00
Jason Aten
016e5e0774 no automatic reuse of Qcx
Per slack discussion with Seebs and Nia,
we'll try not automatically resetting the Qcx.

The worry was that our goroutine shutdown
management is so poor that we are asking for
GetTx on a goroutine that still has a Qcx
from a query that was cancelled.

If this is the case, we will now panic instead of
issuing a new Tx. Then we can fix the poor
goroutine management.

 - also require Qcx.Finish or Abort before Reset
2020-10-30 00:36:46 +00:00
tgruben
51c9f4feeb
Merge pull request #1044 from jaten-molecula/startup_shards
don't apply startup shard cache to roaring with a specified view path
2020-10-29 18:24:57 -05:00
Jason E. Aten
18e253870e cleanup TypedDBPerShardGetShardsForIndex logic 2020-10-29 22:25:06 +00:00
Jason E. Aten
f8e7b27a6f don't apply startup shard cache to roaring with a specified view path
- avoids creating a new empty 8 byte shard file under all the
   views that don't have them already.
2020-10-29 22:09:55 +00:00
tgruben
ed6f59a827
Merge pull request #1042 from jaten-molecula/migration_logging
better migration logging
2020-10-29 04:38:53 -05:00
Jason E. Aten
2d55ffbd28 short circuit if no data to migrate 2020-10-29 02:44:22 +00:00
Jason E. Aten
d4df15721d allow migration of empty to empty 2020-10-29 02:41:09 +00:00
Jason E. Aten
aa47cf5bf4 fix verify test 2020-10-29 02:35:38 +00:00
Jason E. Aten
0e354aedf2 error expected trying to migration to roaring 2020-10-29 02:29:57 +00:00
Jason E. Aten
f9f94aab0d fix typo 2020-10-29 02:15:43 +00:00
Jason E. Aten
bceabc9127 error on un-implemented migrate to roaring 2020-10-29 02:11:28 +00:00
Jason E. Aten
3baa8ea0f6 check if roaring data present with RoaringHasData 2020-10-29 01:47:26 +00:00
Jason E. Aten
639e9b3bf0 quiet 2020-10-29 01:32:04 +00:00
Jason E. Aten
6e20e6439f more logging 2020-10-29 01:30:16 +00:00
Jason E. Aten
b1ff3791b8 better error when green does not exist on migration 2020-10-29 01:20:41 +00:00
Jason E. Aten
85fc785296 timed progress 2020-10-29 01:12:19 +00:00
Jason E. Aten
509348260f better migration logging 2020-10-28 22:54:58 +00:00
Ben Johnson
e332f6fd7e
Merge pull request #1018 from molecula/rbf-cli 2020-10-28 06:26:27 -06:00
jaten-molecula
6386587f12
Merge branch 'master' into rbf-cli 2020-10-28 05:35:43 -05:00
jaten-molecula
9d233c4849
Merge pull request #1040 from jaten-molecula/rowcache_lock
pilosa: write lock the fragment when rowcache used
2020-10-27 20:11:10 -05:00
Jason E. Aten
062bd5c8c7 pilosa: write lock the fragment when rowcache used
- only allocate the rowcache if it is in use (avoid allocation per fragment)
 - when the rowcache is use, fragment.go intRowIterator must write lock the
   fragment because the f.rowCache will be updated.
 - eliminate unused bitmapCache interface to keep the linter happy.
 - fixes #1035
2020-10-28 00:53:38 +00:00
jaten-molecula
1784384153
Merge pull request #1039 from jaten-molecula/rbf_logging
pilosa server --rbf-checkpoint-dur to 0 by default
2020-10-27 18:19:04 -05:00
Jason E. Aten
1ca8a45357 pilosa server --rbf-checkpoint-dur to 0 by default
- we return to checkpointing after every commit, by default.
  - the internal rbf logic is not ready to have
    checkpoints deferred. Doing so results in
    references to WAL segments that are not
    in the current slice of live segments.
2020-10-27 22:38:18 +00:00
jaten-molecula
c9912e3607
Merge branch 'master' into rbf-cli 2020-10-27 15:03:43 -05:00
Cody Soyland
7855cd4d21
Merge pull request #1038 from jaten-molecula/dockerfile_go1.14.10
use go1.14.10 for now because of https://github.com/molecula/pilosa/issues/1036
2020-10-27 14:04:03 -05:00
Jason E. Aten
24bd1543f3 Makefile to go1.14.10 2020-10-27 18:07:13 +00:00
Jason E. Aten
2fb53b982a update .circleci/config.yml to use go1.14.10 2020-10-27 18:00:15 +00:00
Jason E. Aten
03f24303d7 use go1.14.10 for now because of https://github.com/molecula/pilosa/issues/1036 2020-10-27 17:44:53 +00:00
Jason E. Aten
85f3fa9836 merge with the update to rbf to take a Config parameter 2020-10-27 15:11:45 +00:00
jaten-molecula
4543237e09
Merge branch 'master' into rbf-cli 2020-10-27 10:09:24 -05:00
jaten-molecula
305f81a310
Merge pull request #1034 from jaten-molecula/rbf_checkpoint_rb
performance tuning: rbfcfg package, binary search for wal segment
2020-10-27 10:07:47 -05:00
Ben Johnson
2b1d790625 Fix tree key formatting; add --with-tree option 2020-10-27 08:24:56 -06:00
Ben Johnson
7fa1a5edd2 Add RBF CLI commands 2020-10-27 08:12:22 -06:00
Jason E. Aten
957cba1768 performance tuning: rbfcfg package, binary search for wal segment
- rbfcfg package holds Config for --rbf- command line flags
- wal.go: replace linear search with bisection for wal segment
2020-10-27 00:49:56 +00:00
jaten-molecula
14cb29ea7d
Merge pull request #1024 from jaten-molecula/avoid_excessive_directory_scans
pilosa: avoid re-scanning shards during holder open
2020-10-23 20:31:05 -05:00
Jason E. Aten
233b3cbc0f versioned map cleanup 2020-10-24 00:35:25 +00:00
Jason E. Aten
c5e46e4618 one copy of shard map during a reload 2020-10-24 00:20:30 +00:00
Jason E. Aten
8ff6e8e0fd versioned readonly shards map 2020-10-23 23:50:22 +00:00
Jason E. Aten
2503fe5b66 pilosa: avoid re-scanning shards during Holder.Open()
- view.openFragmentInTx was forcing a directory scan
   for shards on every open fragment during Holder.Open().
   Seen by pprof profile having excessive allocations
   from dbshard.go listDirUnderDir().
2020-10-23 23:50:22 +00:00
seebs
2b6cb5fc6c
Merge pull request #1020 from seebs/distinctSet
Distinct operations on set fields
2020-10-23 17:09:23 -05:00
seebs
7558afd7ec
Merge branch 'master' into distinctSet 2020-10-23 16:41:00 -05:00
Cody Soyland
35706a3372
Merge pull request #1017 from codysoyland/docker-build
Fix Docker build target, enable when building Linux releases
2020-10-23 16:31:30 -05:00
Seebs
765d28bf9d add test case and bug fix for distinct code
The "seenThisRow" value was never getting cleared, which meant that
if the first container on a row didn't happen to contain any post-filter
bits, the rest of the row wouldn't get evaluated.
2020-10-23 16:18:19 -05:00
Cody Soyland
fc29bf5ec8 Fix Docker build target, enable when building Linux releases 2020-10-23 14:27:00 -05:00
Seebs
a2151358ba Partial implementation: Distinct() supporting set fields
Add an exported IntersectionAny() from roaring to let us quickly
check whether two containers have overlap, so we can avoid performing
intersections we don't need to when evaluating containers within
the same row as a previous match. (IntersectionCount on the whole
bitmap would imply doing up to 16 intersections even if we find a bit
right away.)

We also allow ForeignIndex to be set on set, mutex, and time fields,
since all of those could now be reasonable operands for Distinct
ops.

Not yet present: Handling time quantums, but that seems really
desireable.
2020-10-23 13:36:40 -05:00
Nia
c1db627593
Merge pull request #989 from niaow/translate-maybe
Allow querying without creating keys
2020-10-23 14:23:35 -04:00
Nia
3b93b767fa
Merge branch 'master' into translate-maybe 2020-10-23 13:59:10 -04:00
Nia Weiss
ddee7ae35e
address review comments for #989 translate-maybe 2020-10-23 10:59:08 -04:00
jaten-molecula
8f1aae9a69
Merge pull request #1016 from jaten-molecula/rowcache_optional
pilosa server --rowcache-off disables the row cache
2020-10-22 22:14:51 -05:00
Jason E. Aten
8d2ad048fa pilosa server --norowcache disables the row cache
- this can lessen memory pressure
- certain backends may not need it
- enables performance benchmarking and tuning
2020-10-22 22:20:48 +00:00
seebs
9eb251ec85
Merge pull request #69 from seebs/ctbench
Container op benchmarks
2020-10-22 15:03:09 -05:00
Seebs
8095455355 container performance benchmarking
This adds a series of archetypal containers that represent the
common use cases (arrays, bitmaps, or runs of various cardinalities)
and runs the basic operations against them for benchmarking purposes.

`benchpretty` is an app to snatch the BenchmarkCt* lines from
benchmark runs and display them in a possibly more usable form,
mostly as a precursor to cool analysis things.

This also adds a test to verify that intersectionCount(a, b)
is the same as intersect(a, b).N() for all the archetypal
containers.

This also includes a performance fix for intersectBitmapRun which
was spotted while running these tests.
2020-10-22 14:33:03 -05:00
Nia Weiss
afbbc93047
add basic tests for queries with missing keys 2020-10-22 13:19:05 -04:00
Nia Weiss
9204298d06
fix broken rebase on GetNodeUsage 2020-10-22 11:10:36 -04:00
Nia Weiss
8340b9ea64
re-apply single equals fix 2020-10-22 11:03:51 -04:00
Nia Weiss
b0a588f8dd
finish translate-if-exists 2020-10-22 10:50:09 -04:00
Nia Weiss
a74eda1eb0
cleanup of key translation fix 2020-10-22 10:50:08 -04:00
Nia Weiss
c60c699664
deal with linter false positives 2020-10-22 10:47:30 -04:00
Nia Weiss
da52b134bf
the tests pass now 2020-10-22 10:47:30 -04:00
Nia Weiss
5315579378
add some validation 2020-10-22 10:47:29 -04:00
Nia Weiss
1fe0edae08
fix find & create foreign index keys 2020-10-22 10:47:29 -04:00
Nia Weiss
a6e3723190
it mostly works now 2020-10-22 10:47:29 -04:00
Nia Weiss
13a19aeb42
query translation WIP 2020-10-22 10:47:29 -04:00
Nia Weiss
15036787a7
test new translation paths via API 2020-10-22 10:47:29 -04:00
Nia Weiss
8a130c150e
address review comments 2020-10-22 10:47:28 -04:00
Nia Weiss
22d6011d05
apply "maybe" key translation WIP 2020-10-22 10:47:25 -04:00
jaten-molecula
d12639b890
Merge pull request #1014 from jaten-molecula/log_in_utc
log in UTC in fixed width microseconds RFC3339 format
2020-10-21 20:01:36 -05:00
Jason E. Aten
aad38d1c60 log in UTC in fixed width microseconds 2020-10-21 18:36:28 +00:00
seebs
4cea813ae8
Merge pull request #999 from seebs/pqlCleanup
Fixes some minor PQL issues; adds support for case-insensitive PQL calls
2020-10-20 16:02:42 -05:00
jaten-molecula
fb6feb04f9
Merge branch 'master' into pqlCleanup 2020-10-20 15:21:54 -05:00
seebs
a1e1d86ae3
Merge pull request #1012 from seebs/ignoreCN
Supply "subject alternative name" for TLS certificates
2020-10-20 14:50:18 -05:00
Travis Turner
52b91b2df1
Merge branch 'master' into pqlCleanup 2020-10-20 14:19:45 -05:00
Seebs
5e36638e10 Supply "subject alternative name" for TLS certificates
Go killed off using the common name for hostnames starting with 1.15,
but this can be addressed by recreating the certs using a Subject
Alternative Name for the domain for "localhost". This allows tests
to pass without hanging, at least for me.
2020-10-20 14:14:26 -05:00
jaten-molecula
d929c945bc
Merge pull request #1011 from jaten-molecula/rbf_default
rbf is the default Tx type. Dogfood it.
2020-10-20 13:53:21 -05:00
Jason E. Aten
18ad4a8230 rename test-golang-1.14 -> test-golang-1.14.9 2020-10-20 13:37:13 -05:00
Travis Turner
4db93db0c1
Merge branch 'master' into pqlCleanup 2020-10-20 13:19:55 -05:00
Jason E. Aten
275779173d go1.15.3 support with GODEBUG=x509ignoreCN=0 2020-10-20 12:23:35 -05:00
Jason E. Aten
996b2ccb23 go1.13.15 -> go1.15.3 as our supported versions 2020-10-20 11:58:12 -05:00
Jason E. Aten
1216b93d73 rbf is the default Tx type. Dogfood it. 2020-10-20 11:07:07 -05:00
tgruben
c356498c19
Merge pull request #1010 from jaten-molecula/avoid_bg_deadlock
CI catches red blue-green tests. Qcx write flag
2020-10-20 11:01:53 -05:00
Travis Turner
7be3cd6a36
Merge branch 'master' into pqlCleanup 2020-10-20 10:59:48 -05:00
Jason E. Aten
2b4e6d25f5 CI catches red blue-green tests. Qcx write flag
- fix a CI/Makefile issue that was hiding red tests in CI.
 - the testv and testv-race targets now require /bin/bash
 - In executor.go, the top-level query context Qcx now
   has a write flag. It will upgrade read-Tx to write-Tx
   when Store() wraps some inner local-read operations,
   to avoid deadlocking against its own query. This deadlock
   happens in TestExecutor_Execute_SetRow/Set_NewRow
   under rbf_lmdb blue-green testing without the upgrade.
2020-10-20 10:38:40 -05:00
jaten-molecula
0dd3486b95
Merge pull request #1005 from jaten-molecula/bglimits
Fix blue-green Tx cleanup and document single import at once
2020-10-20 07:31:54 -05:00
Jason E. Aten
d9783406bd Fix blue-green Tx cleanup and document single import at once
- correct string constants for txtype so that
  blue-green cleanup correctly detects when
  2nd transaction in a pair has Committed and
  thus the blue-green RWMutex can be relased

- test that txtype.String() is consistent with
  the corresponding string constants.

- document in bluegreentx.go the current limitations
  of blue-green testing: only one github archive import
  (a single writing client) is supported by blue-green
  testing. Multiple importers will deadlock eventually
  on the DBShard.mut RWMutex. We could fix this by
  ordering the write locks and obtaining them in
  strictly increasing order (by shard number), but
  that would require alot of change to the executor
  and that would introduce more risk for a test-only
  pathway.
2020-10-20 07:09:08 -05:00
jaten-molecula
2ebff707a9
Merge pull request #1004 from jaten-molecula/bluegreenlock
introduce a per shard blue-green RWMutex
2020-10-19 18:02:29 -05:00
Jason E. Aten
81013999e5 introduce a per shard blue-green RWMutex
- allows blue-green testing with concurrent readers/writers.
 - otherwise we don't start/end the blue and green Tx
   together, and they get split by a read/write concurrently.
2020-10-19 17:28:35 -05:00
Travis Turner
f37a63e5cf
Merge branch 'master' into pqlCleanup 2020-10-19 15:45:04 -05:00
Cody Soyland
d3ae2614ce
Merge pull request #1001 from seebs/updateLint
uprev golangci-lint, fix a minor lint in rbf
2020-10-19 14:54:38 -05:00
Seebs
ed309821ae uprev golangci-lint, fix a minor lint in rbf
I have a newer staticcheck and golangci-lint on my laptop, and it started
complaining about something. The first comment added disables the check
in staticcheck-as-a-command, the second disables it when it's being done
by golangci-lint, which invokes the analysis passes directly and displays
the output differently, and also doesn't recognize the hints used by
staticcheck.

Newer golangci-lint doesn't find anything else that it wants to complain
about.
2020-10-19 14:25:11 -05:00
Seebs
6e725d50ce check error return from peg parser Init
The updated peg tool produces an Init that can return an error. As
of this writing, the error can't be non-nil unless you specified an
option which itself returned an error, but that could change later,
so let's be careful.
2020-10-19 13:47:42 -05:00
Seebs
e84d2d2a59 refactor number parsing a bit
There are subtle inconsistencies, like "01" being a valid decimal but not
a valid integer, which vaguely bug me. Cleaning this up, and the corresponding
parser logic.

A number can't have leading spaces because the grammar doesn't
put spaces in them in the first place, so stop accepting them in the
number syntax. This should never have any impact on anything,
it's just simpler.

Update a couple of test cases to reflect this -- no longer testing
that trailing spaces are okay, now testing that they're not, for
instance.
2020-10-19 13:37:21 -05:00
Seebs
c19d571112 more consistent spacing
We still prohibit a space before a leading '(', which maybe we shouldn't,
but we now allow spaces on both sides of a closing ')' more consistently.
Drop the unneeded "sp" before "close" in the special handling after
null, true, and false, because close now implies that.

Also, refactored the two instances of "sp '=' sp" into a thing called eq,
which may not be worth it.
2020-10-19 13:35:49 -05:00
Seebs
28d18920b9 Make PQL case-insensitive about call names.
Use "" strings for fixed string names. In startCall(), look up the
lowercase conversion of a call name in a table mapping all-lowercase
representations to canonical case, so we don't have to chase down
everyplace in the rest of the code base that assumes "Row" is
capitalized exactly like that.
2020-10-19 13:35:49 -05:00
Seebs
18ed02d7fb drop float/decimal distinction in PQL
PQL always produces decimals, which have effectively-arbitrary range,
but can convert them to floats when required; the executor then requests
this conversion in the handful of cases (SetRowAttrs and SetColumnAttrs)
where it wants floats rather than decimals.

Not yet fixed: The "Range" call may also be wrong now. It was specifying
an "fvalue" but is now effectively getting what used to be called a
"dvalue". However, so far as I can tell, that didn't work before either.
2020-10-19 13:35:49 -05:00
Seebs
b8bb438b69 trivial cleanup of PEG grammar
Drop irrelevant (), simplify the expression of the sp rule.

Perhaps shockingly, this *does not change the generated grammar at all*. The
generated code for:
	sp <- [ \t\n]*
and is identical to the code for:
	sp <- ( ' ' / '\t' / '\n' )*

And in fact, is spelled the latter way in the generated comments.
2020-10-19 13:35:49 -05:00
Seebs
0ea324129f update to new version of peg tool
Want to do some PQL cleanup. A new version of peg turns out to dramatically
alter performance in some cases, so I'm doing the commit for "don't change any
PQL, just change the version of peg" checkin separately.
2020-10-19 13:35:49 -05:00
tgruben
092177aea4
Merge pull request #997 from molecula/bolt_in_badger_out
Use boltdb instead of badger as our all-Go Tx oracle
2020-10-16 17:41:23 -05:00
Jason E. Aten
266b92c025 Use boltdb instead of badger as our all Go Tx oracle.
- remove all badgerdb code.
 - use boltdb instead.
2020-10-16 17:21:21 -05:00
Cody Soyland
3dff03907d
Merge pull request #942 from codysoyland/grpc-web
Add grpc-web to http handler
2020-10-16 15:46:25 -05:00
Cody Soyland
b86b0519af go mod tidy 2020-10-16 15:10:48 -05:00
Cody Soyland
a2ee047868 grpc-web cors test 2020-10-16 11:36:41 -05:00
Cody Soyland
31cd119a7e Move grpc.Server creation into initializer
This fixes an issue with the grpc-web middleware using a nil
grpc.Server instance.
2020-10-16 11:36:41 -05:00
Cody Soyland
04b1152224 Add grpc-web to http handler 2020-10-16 11:36:41 -05:00
jaten-molecula
8da638f685
Merge pull request #979 from seebs/bbolt
switch to etcd boltdb fork
2020-10-15 19:58:31 -05:00
Seebs
0905e858cd uprev golang to 1.14.9
1.14 had a bug in the checkptr code (well, not exactly a bug) which
made it enforce alignment requirements on x86. This turns out not
to be the problem I was seeing, but we should be on 1.14.9 anyway.

To keep this from breaking CI integration with Github, we also
use explicit job names instead of matrix-generated ones, and fix
the CI config syntax up a bit after almost getting that right the
first try. (This patch includes fixes contributed by Cody, and since
I had to rebase and re-approve AGAIN anyway, I might as well squash
the commit history up.)
2020-10-15 19:13:28 -05:00
Seebs
76fe49d390 un-disable checkptr by fixing the memory problems
Step one: switch to etcd.io's bbolt fork of boltdb.

The etcd-io fork of boltdb isn't archived, and has fixes for boltdb's
interactions with checkptr, allowing us to drop the checkptr-disabling
hackery.

This seems to be a drop-in replacement; etcd/bbolt says that the file
format is "fixed" (I believe in the sense of "unchanging"), and I can
run pilosa on an existing data directory with this.

Step two:

Fix missing caps in roaring.go that were also triggering the same
issues.
2020-10-15 19:12:47 -05:00
tgruben
de642ed90c
Merge pull request #993 from molecula/fix983
bluegreentx: default to not dumping full databases
2020-10-15 17:31:55 -05:00
Jason E. Aten
e5a56f1cd2 bluegreentx: default to not dumping full databases 2020-10-15 16:23:19 -05:00
Matthew Jaffee
c859a8aa2b
Merge pull request #981 from jaffee/single-equal-data-race
Fix data race on call map in single '=' logic
2020-10-15 11:40:16 -05:00
Matt Jaffee
00f1f70779
fix data race on call map in single = logic
Add test of single = int query over multiple shards which reproduces
the race

move the code which modifies the PQL call object if a Row query
on an int field uses a single = instead of ==. Instead of processing
this at the shard level, we'll process it during the initial
translation step so that it isn't operated on concurrently.
2020-10-15 10:26:14 -05:00
alanbernstein
4bf81444ba
Merge pull request #951 from molecula/shard-dist-api
Add ui-specific endpoint to report shard distribution data
2020-10-14 21:58:05 -05:00
Alan Bernstein
94e82aea86 Consider available shards 2020-10-14 21:11:02 -05:00
Alan Bernstein
ab502a0f8d Add basic test 2020-10-14 21:11:02 -05:00
Alan Bernstein
510902625e Update test hasher implementations 2020-10-14 21:11:02 -05:00
alan
2a902b3a7b Finish basic shard-distribution endpoint 2020-10-14 21:11:02 -05:00
Alan Bernstein
98cd2dc441 WIP shard distribution endpoint 2020-10-14 21:11:02 -05:00
Cody Soyland
8c9569faca
Merge pull request #982 from codysoyland/circle-config-fix
Fix PR detection logic in CI
2020-10-14 21:07:23 -05:00
Cody Soyland
316bd87a8a Fix PR detection logic in CI 2020-10-14 20:36:04 -05:00
jaten-molecula
fa21c81a27
Merge pull request #963 from molecula/rbf_config
rbf: add DBConfig
2020-10-14 20:12:46 -05:00
jaten-molecula
577600d17b
Merge branch 'master' into rbf_config 2020-10-14 19:57:05 -05:00
jaten-molecula
39a31cc63e
Merge pull request #976 from seebs/impossible
Check more carefully for, and also fix, containers with invalid N
2020-10-14 18:57:02 -05:00
jaten-molecula
eb4b9974ac
Merge branch 'master' into impossible 2020-10-14 18:40:50 -05:00
alanbernstein
ca223c4a79
Merge pull request #934 from alanbernstein/cluster-usage
Collect size-on-disk usage data from all nodes
2020-10-14 16:33:03 -05:00
Alan Bernstein
aff5c0fc57 Skip missing directories 2020-10-14 15:46:19 -05:00
Jason E. Aten
244ba21da7 better names 2020-10-14 13:19:14 -05:00
Jason E. Aten
3a40b586b3 disk usage per index 2020-10-14 12:53:35 -05:00
Alan Bernstein
e2cafd98ef Move index size calculation to TxFactory 2020-10-14 12:20:05 -05:00
Alan Bernstein
7a32eadc64 Move disk capacity lookup to gopsutil wrapper package 2020-10-14 12:20:05 -05:00
Alan Bernstein
6a298590be Set omitempty for disk capacity json 2020-10-14 12:20:05 -05:00
Alan Bernstein
ba4ca1a93e Include disk capacity in usage response 2020-10-14 12:20:05 -05:00
Alan Bernstein
2a44bdd25c Collect size-on-disk usage data from all nodes 2020-10-14 12:20:05 -05:00
Cody Soyland
e1e0b298f5
Merge pull request #964 from codysoyland/check-changelog-label
Check for changelog label in CI
2020-10-14 10:11:45 -05:00
Seebs
c88192b4ac Check more carefully for, and also fix, containers with invalid N
In rare cases, RBF can produce containers which have a recorded N value which
is incorrect. This rarely affects anything, but on some particular queries,
this can result in very strange outcomes, like array containers with more
than 1<<16 entries.

To fix this, we have toContainer specify that it doesn't know the correct
N for the bitmap containers it's creating, which costs extra time for counting,
and should be considered a temporary workaround.

Also, we add a CheckN() function which is controlled by the
roaringparanoia flag, and add a number of calls to it, for instance, as
deferred calls after every container operation when roaringparanoia is
enabled. This means that we get improved confidence that we've caught
the relevant errors, but is not suitable for production use.
2020-10-14 10:03:18 -05:00
Cody Soyland
ca5dbe8d39 Fix pull request filter 2020-10-14 09:42:07 -05:00
Cody Soyland
2ac09af894 Only run on pull requests 2020-10-14 09:29:51 -05:00
Cody Soyland
4e66bbb76b Check for changelog label in CI 2020-10-14 09:29:51 -05:00
seebs
6c14aa965d
Merge pull request #895 from seebs/appendSemantics
use append-like semantics consistently for *Container
2020-10-14 09:04:56 -05:00
jaten-molecula
3d4da8f51b
Merge branch 'master' into appendSemantics 2020-10-14 07:24:18 -05:00
jaten-molecula
20d4268676
Merge branch 'master' into rbf_config 2020-10-14 07:19:37 -05:00
jaten-molecula
a997e713dc
Merge pull request #977 from molecula/readers
pilosa-fsck: the -readers flag controls parallelism
2020-10-13 19:14:09 -05:00
Jason E. Aten
50a8db854d pilosa-fsck: the -readers flag controls parallelism
- add path info to the panic if we find a corrupt boltdb
   translation store.
2020-10-13 18:58:38 -05:00
J
3ad8ec7f0f rbf: add runtime options to DB struct
- FsyncEnabled and DoAllocZero moved to DB struct.
 - deletes unused xrbrsupport.go and cmd/convert
 - fixes #941
2020-10-12 18:35:00 -05:00
tgruben
db9e8cd8ef
Merge pull request #966 from molecula/fix843
pilosa/dbshard: allow deleteIndex and then re-use of index
2020-10-12 18:10:04 -05:00
Jason E. Aten
b3e6cdc0d8 pilosa/dbshard: allow deleteIndex and then re-use of index
- fixes #843
2020-10-12 17:46:06 -05:00
jaten-molecula
54255eae15
Merge pull request #957 from molecula/fix-tx-deadlock
Fix deadlock in importWorker()
2020-10-12 17:04:11 -05:00
Ben Johnson
676208ea73 Add test to reproduce deadlock 2020-10-12 12:32:58 -06:00
Ben Johnson
9b83b71c8f Fix error check reference in importWorker() 2020-10-12 11:28:18 -06:00
Ben Johnson
bfe570ef9d Fix deadlock in importWorker()
This commit wraps the work for a view in a function so that the
defer on the finisher executes after each view is processed instead
of at the end.
2020-10-12 11:25:28 -06:00
Cody Soyland
279be13a46
Merge pull request #958 from codysoyland/grpc-compat-update
Better VDSM gRPC compatibility
2020-10-12 09:27:04 -05:00
Cody Soyland
e40b224a4f
Merge branch 'master' into grpc-compat-update 2020-10-12 09:08:42 -05:00
tgruben
d3811634d6
Merge pull request #959 from molecula/parallel_fsck
pilosa-fsck: parallelize Index.ComputeTranslatorSummary
2020-10-09 16:12:36 -05:00
Jason Aten
8da15b18d4 pilosa-fsck: parallelize Index.ComputeTranslatorSummary
- add -index option
2020-10-09 15:53:29 -05:00
Cody Soyland
6c10917ceb Use vdsm.QueryPQLRequest for vdsm.QueryPQLUnary 2020-10-09 13:34:20 -05:00
Cody Soyland
3039aa44af Use copy of vdsm InspectRequest for better compatibility 2020-10-09 13:22:24 -05:00
Cody Soyland
a58c345232 Use copy of vdsm QueryPQLRequest for better compatibility 2020-10-09 13:22:24 -05:00
tgruben
d3ce4fa70e
Merge pull request #948 from molecula/randomquery
pilosa/cmd/random-query: generate random queries from existing schema/data
2020-10-09 12:16:28 -05:00
Jason Aten
937a1afade pilosa/cmd/random-query: generate random queries from existing schema
- fixes molecula/molecula#136
 - flag -n 0 does continuous queries until process is killed.
2020-10-08 18:38:01 -05:00
jaten-molecula
06ee8b16ac
Merge pull request #940 from molecula/fsck_2index_repair
pilosa-fsck: multi-index counts and repairs.
2020-10-07 07:35:08 -05:00
Jason Aten
a63c6ee2b2 pilosa-fsck: multi-index counts and repairs.
- multiple indexes repaired at once could crosstalk. Fixed.
 - the counts of keys and ids are now broken down by index.
2020-10-06 21:10:52 -05:00
tgruben
d41de17503
Merge pull request #931 from molecula/fsck_msg
pilosa-fsck: correct repair -> analysis in pilosa-fsck logging
2020-10-06 13:21:21 -05:00
jaten-molecula
bc8fc23ac9
Merge branch 'master' into fsck_msg 2020-10-06 13:12:46 -05:00
tgruben
3a742a0caa
Merge pull request #938 from molecula/ci_rbf
run CI on rbf and rbf_lmdb
2020-10-06 12:52:33 -05:00
Jason Aten
83f230bbfb run CI on rbf and rbf_lmdb 2020-10-06 12:22:03 -05:00
Ben Johnson
ab6581446d
Merge pull request #889 from molecula/rbf-immutable-wal 2020-10-06 10:45:47 -06:00
Ben Johnson
3b7758a4f2 Add comment explaining rbf.DB.checkpoint() args 2020-10-06 10:36:57 -06:00
Ben Johnson
2440413c49 Remove test skips based on race detector 2020-10-06 10:29:17 -06:00
Ben Johnson
7b64abbb53 Reduce default RBF DB size to 4GB; remove race skips 2020-10-06 09:36:31 -06:00
Ben Johnson
644969e6a9 Add log.* and tourna.* to gitignore 2020-10-06 09:36:31 -06:00
Ben Johnson
265452cf3d Add rbf.SyncEnabled 2020-10-06 09:36:31 -06:00
Ben Johnson
cf208cfaa3 Increase test http client timeout
The timeout was increased to allow additional time for RBF to process
a lot of individual `Set()` commands in `TestMain_RecalculateHashes`.
2020-10-06 09:36:31 -06:00
Ben Johnson
3852ac79c4 Add rbf.DB.TxN() function and test check 2020-10-06 09:36:31 -06:00
Ben Johnson
c978e2242e Skip some RBF tests during race detection 2020-10-06 09:36:31 -06:00
Ben Johnson
c51ba69c09 Fix RBF sync calls 2020-10-06 09:36:31 -06:00
Ben Johnson
3429421148 Fix RBF checkpoint off-by-one WAL ID issue 2020-10-06 09:36:31 -06:00
Ben Johnson
d826cec4b3 fix RBF WAL segment reference error 2020-10-06 09:36:31 -06:00
Ben Johnson
cdd10a26f0 Refactor RBF to use immutable list of WAL segments.
Previously, RBF shared a list of WAL segments between the DB & Tx.
However, this increased the need for mutexes to access the data.

WAL segments are effectively immutable on-disk so the list of segments
has been refactored so that changes to the segment list are done via
copy-on-write which allows read transactions to access segment data
without a mutex.

The database checkpointing can remove early, unused segments and
there is an update/add check to make sure that Tx segments pushed back
to the DB do not include removed segments.
2020-10-06 09:36:31 -06:00
tgruben
8dbfaf5045
Merge pull request #932 from jaten-molecula/pr919
api usage should ignore tx stores. fixes #919
2020-10-06 09:45:43 -05:00
jaten-molecula
ce3a51eb87
Merge branch 'master' into fsck_msg 2020-10-06 09:28:36 -05:00
Jason Aten
6ddeec2ee8 print time at end of fsck run, even if we return 1 to shell 2020-10-06 08:19:53 -05:00
jaten-molecula
4ca42d7f14
Merge branch 'master' into pr919 2020-10-05 21:29:28 -05:00
Travis Turner
12cd4ea69e
Merge pull request #922 from travisturner/design-typos
adjust some wording and typos in the fsck design doc
2020-10-05 20:57:44 -05:00
Jason Aten
c82a1593ff api usage should ignore tx stores. fixes #919
- avoid deadlock in txfactory_internal_test w Qcx
2020-10-05 20:51:38 -05:00
Jason Aten
2f9c51349a correct repair -> analysis in pilosa-fsck logging 2020-10-05 19:59:32 -05:00
Travis Turner
69e15b4719
Merge branch 'master' into design-typos 2020-10-05 18:45:24 -05:00
jaten-molecula
d55ce8723b
Merge pull request #917 from molecula/pr224
ensure that Inspect generates a result for every header item
2020-10-05 17:37:15 -05:00
jaten-molecula
a14b81edbf
Merge branch 'master' into design-typos 2020-10-05 17:29:42 -05:00
Kuba Podgórski
5e2a14400a
Add an extra else branches 2020-10-05 17:13:48 -05:00
Jason Aten
fd87e8d2f3
follow suggestion on https://github.com/molecula/idk/issues/224, does it fix Q2 delete consumer issue?
- apparently not, but this might still be worth doing.
2020-10-05 17:13:48 -05:00
Nia
84830d8361
Merge pull request #921 from niaow/fix-rows-type-error
Generate errors for all unsupported types in Rows calls
2020-10-05 16:32:37 -04:00
Travis
675373f0f3
adjust some wording and typos in the fsck design doc 2020-10-05 14:38:57 -05:00
Nia Weiss
bb0d8bea14
generate errors for all unsupported types in Rows calls 2020-10-05 15:37:05 -04:00
jaten-molecula
9d7945e5be
Merge pull request #918 from molecula/fsck-design
DESIGN.md for pilosa-fsck
2020-10-05 13:36:57 -05:00
Jason E. Aten
05d4b664df groom 2020-10-05 13:29:29 -05:00
Jason E. Aten
9dacbccf8d DESIGN.md for pilosa-fsck
- Orient users to pilosa-fsck by giving an overview of its operations.
2020-10-05 12:51:26 -05:00
jaten-molecula
75b8fa0aa8
Merge pull request #900 from molecula/pilosa-fsck-rb
pilosa-fsck: fsck-like scan and repair of pilosa backups
2020-10-02 16:53:57 -05:00
Jason E. Aten
fe425a84c0 pilosa-fsck: scan and repair of pilosa backups
- the -fix flag repairs replication errors by copying from the primary.
 - the -fixkeys flag repairs any string key translation issues.
 - make pilosa-fsck installs pilosa-fsck and builds release-pilosa-fsck.COMMIT.GOOS.tar.gz release tarbar
2020-10-02 16:47:56 -05:00
jaten-molecula
d9f8de170c
Merge pull request #906 from jaffee/revert-confirm-down-retries
retrun confirmDownRetries to 10, tourney mac compatible
2020-10-02 15:15:57 -05:00
Matt Jaffee
c2a93cc886
retrun confirmDownRetries to 10, tourney mac compatible
At some point the cluster code was modified to do 120 tries to confirm
if a node was down which is a bit excessive for production. My
understanding is that this was done to help trigger or fix a problem
during testing which is hopefully no longer relevant.

Also changed the tournament script to use what I think are more
standard bash-isms that work on mac. Please confirm this still works
on Linux as well.
2020-10-02 14:24:16 -05:00
seebs
df89ebf394
Merge pull request #844 from seebs/setRowCache
Update cache entries when setting a row even in shards with no new data
2020-10-02 13:20:54 -05:00
Seebs
aec11ff713 Update cache entries when setting a row even in shards with no new data
The logic assumes that the lack of a corresponding rowSegment means that
there's no changes, but that's not true -- we just deleted all the
existing data! Update to match clearRow behavior better.

Also, add a corresponding test case for this.

Also, change references to 'defaultSnapshotQueue' to use
[fragment].holder.SnapshotQueue, because defaultSnapshotQueue was
the queueless queue, but holders were getting a snapshot queue,
meaning that "awaiting" a snapshot could result in moving on
and closing the holder before the actual snapshot queue finished
snapshotting.
2020-10-02 12:57:18 -05:00
Nia
7006233cf8
Merge pull request #915 from niaow/distinct-error-handling
Fix panic when "field" parameter not present on Distinct call (error instead)
2020-10-01 14:58:29 -04:00
Nia
ad0f0b1725
Merge branch 'master' into distinct-error-handling 2020-10-01 14:47:16 -04:00
alanbernstein
afc6f432bd
Merge pull request #647 from alanbernstein/ui-feature-support
Add more info to some endpoints to support UI
2020-10-01 13:19:35 -05:00
Nia Weiss
415f7d20b8
add field parameter error handling to Distinct 2020-10-01 12:09:34 -04:00
Alan Bernstein
8a3d93fe78 Move TransactionList endpoint to UI namespace 2020-10-01 10:45:08 -05:00
Alan Bernstein
46d010fe18 Remove 'NodeStates' from /status until it is reliable 2020-10-01 10:43:49 -05:00
Alan Bernstein
1a04e94fc1 Remove clusterID and default name to ID 2020-10-01 10:43:49 -05:00
Alan Bernstein
5705b45864 Add a CLI flag for cluster name and include it in /status response 2020-10-01 10:43:49 -05:00
Alan Bernstein
8fad2b92c2 Add all node states to /status response 2020-10-01 10:43:49 -05:00
Alan Bernstein
664c911791 Include replicaN in /info response 2020-10-01 10:43:49 -05:00
alanbernstein
11e4bbfc67
Merge pull request #907 from alanbernstein/cluster-data-endpoint
Add single-node 'bytesOnDisk' object to /status response
2020-10-01 10:42:27 -05:00
Alan Bernstein
b6af0e5219 Move usage data to new ui-specific endpoint 2020-10-01 10:25:48 -05:00
Alan Bernstein
6f2fe3afe1 Address linter issue 2020-10-01 10:25:48 -05:00
Alan Bernstein
474261f12f Add single-node 'bytesOnDisk' object to /status response 2020-10-01 10:25:48 -05:00
Nia
cac89f4c96
Merge pull request #913 from niaow/misaligned-distinct
Fix misaligned bitmaps in Distinct
2020-10-01 11:17:29 -04:00
Nia Weiss
e0f9870378
fix misaligned bitmaps in Distinct
This resolves an issue in which a filter would eliminate all bits in all shards other than shard 0.
2020-10-01 10:07:08 -04:00
Nia
f030792b8a
Merge pull request #905 from niaow/syncrace
Fix race condition when resetting translation
2020-09-30 09:26:43 -04:00
Nia
c31d2f143c
Merge branch 'master' into syncrace 2020-09-30 09:17:59 -04:00
Cody Soyland
86c5e040b1
Merge pull request #870 from codysoyland/grpc-compat
Fully backwards-compatible VDSM gRPC interface
2020-09-29 15:58:20 -06:00
Jason Aten
0e8564e2be fix license exceptions for vdsm/proto 2020-09-29 15:30:41 -05:00
Cody Soyland
949ca882fc Remove unused helper func 2020-09-29 15:30:12 -05:00
Cody Soyland
fdce92eb40 Use shared types from pilosa proto file and enable generic proxying of query calls 2020-09-29 15:30:12 -05:00
Cody Soyland
83704e7973 Proxy unary methods to Pilosa gRPC handler 2020-09-29 15:29:37 -05:00
Cody Soyland
c1e50ed909 Remove VDS references from pilosa proto file, begin porting VDSM service 2020-09-29 15:29:37 -05:00
Nia Weiss
1b210080c6
fix race condition when resetting translation
Previously, we never waited for translation sync goroutines to stop.
That issue should be mostly harmless in the normal path.
Additionally, this waits for the translation sync to shut down when stopping the server.
2020-09-29 13:54:16 -04:00
Seebs
fbb648b1fb enforce append-like semantics for *Container more consistently
The copy-on-write/rowCache changes require that functions that
modify containers be able to generate new containers. Once that
became possible, some significant pool of other operations
started relying on it -- for instance, operations might return
a new container even though they're in theory "in place" operations.

I developed a tool for checking for unused function return
values (github.com/molecula/noticeme), and ran it on this, and
picked out the places where `*Container` values were generated
but not used, and some of them seem to be potentially-real
bugs, and a few are probably harmless. Updated code to make
those diagnostics go away.
2020-09-28 12:19:24 -05:00
tgruben
82cdffd309
Merge pull request #899 from jaten-molecula/better_err_on_closed_db
better error reporting when making Tx on closed lmdb
2020-09-26 09:59:15 -05:00
Jason Aten
5a3170a9a4 better error reporting when making Tx on closed lmdb
- return error instead of panic.
2020-09-26 06:24:58 -05:00
Nia
3d07d13a7c
Merge pull request #897 from niaow/no-explicit-recalculate
Stop explicitly recalculating caches in tests
2020-09-25 11:18:37 -04:00
Nia Weiss
79f68f7a2e
stop explicitly recalculating caches in tests
This is no longer necessary, as caches now recalculate on read.
Also, in general a user will not explicitly request recalculation, so it would make sense for our tests to reflect that.
2020-09-25 10:36:00 -04:00
jaten-molecula
f026c43649
Merge pull request #891 from molecula/optimize_directadd
Bitmap.DirectAdd avoids returning overfull containers
2020-09-23 17:25:29 -05:00
Jason Aten
7ae8accfa8 Bitmap.DirectAdd avoids returning overfull containers
- log Debugf when we repair a fragment block
- better run-run roaring testing for over-sized containers
- add which fragment path to panic on container too big
- include container contents in roaring hash for pilosa-chk/pilosa-check-backup
2020-09-23 17:13:25 -05:00
Nia
4b5572da1d
Merge pull request #893 from niaow/limit-cluster
Fix Limit when used as an input to another query
2020-09-23 13:51:11 -04:00
Nia
e0f25f1d20
Merge branch 'master' into limit-cluster 2020-09-23 13:46:02 -04:00
Nia Weiss
2158417f34
fix Limit when used as an input to another query 2020-09-23 13:08:48 -04:00
Kuba Podgórski
8b855b97d0
Merge pull request #892 from kuba--/fix-545
Translate field IDs on coordinator
2020-09-23 17:49:15 +02:00
Kuba Podgórski
ba5438e02b Trabnslate field IDs on coordinator 2020-09-23 15:21:33 +02:00
jaten-molecula
f7afd5d2e1
Merge pull request #875 from molecula/remove_debug_tooling
turn on row cache. tx: remove debug tooling
2020-09-22 15:56:02 -05:00
Jason Aten
55d4c29933 turn off debug machinery on tx backends
- enable row cache again. Was off for tx perf measurement.
 - centralize UseRowCache choice to just one point, in rbf.EnableRowCache
2020-09-22 15:47:52 -05:00
Kuba Podgórski
886318931d
Merge pull request #882 from kuba--/fix-869
Fix holes in grpc response for inspect
2020-09-22 14:20:10 +02:00
Kuba Podgórski
b54a289cd8 Fix holes in grpc response for inspect 2020-09-22 12:02:26 +02:00
jaten-molecula
ba2851229d
Merge pull request #871 from molecula/bluegreen_verify
blue_green verify accepts empty fragments
2020-09-18 11:55:22 -04:00
Jason Aten
57be5392cf blue_green verify accepts empty fragments 2020-09-18 10:49:36 -05:00
tgruben
8ec10ec1e8
Merge pull request #868 from molecula/with_primary_instead_owner
Translate only on coordinator/primary
2020-09-17 17:12:56 -05:00
Kuba Podgórski
650244214d Translate only on coordinator/primary
- This is the commit message #3:
2020-09-17 17:03:29 -05:00
jaten-molecula
7dc59c4d9c
Merge pull request #831 from molecula/rbf-tx-cursor-stack-allocate
Stack allocate return from rbf.Tx.cursor()
2020-09-16 23:40:32 -04:00
Jason Aten
9b99009871 allow rbf-tx-cursor-stack-allocate to merge; fix conflict with the new HasData code 2020-09-16 22:35:30 -05:00
jaten-molecula
c04642f34b
Merge branch 'master' into rbf-tx-cursor-stack-allocate 2020-09-16 23:21:35 -04:00
jaten-molecula
0f5838816b
Merge pull request #857 from molecula/rbf-fix-direct-write-corruption
Fix RBF write corruption during direct write.
2020-09-16 23:07:57 -04:00
jaten-molecula
71033f78b5
Merge branch 'master' into rbf-fix-direct-write-corruption 2020-09-16 22:32:47 -04:00
Nia
16c5212e2d
Merge pull request #858 from niaow/deprecate-inspect
Add a deprecation warning to Inspect
2020-09-16 15:31:57 -04:00
Nia Weiss
f03ba0e682
add a deprecation warning to Inspect 2020-09-16 12:30:12 -04:00
Ben Johnson
6918fe2f60
Merge branch 'master' into rbf-fix-direct-write-corruption 2020-09-16 09:55:26 -06:00
jaten-molecula
75b01ba87d
Merge pull request #850 from molecula/db_has_data_rb
blue_green verification and migration capabilities.
2020-09-16 11:22:34 -04:00
Ben Johnson
458984c756 Fix RBF write corruption during direct write.
This commit fixes an issue where direct writes would overwrite the
source page where data was being copied from because writes are
immediate (instead of going to the WAL first).
2020-09-16 08:59:53 -06:00
Jason Aten
31d54010f8 blue_green verification and migration capabilities.
- on startup in blue_green mode, we will migrate
   blue to green if blue is empty.
 - otherwise, when blue has data, we verify
   against green before proceeding with the
   blue_green run.
 - small optimization in the rbf cursorx.go to
   short-circuit processing on a nil bitmap.
   This avoids a roaringparanoia tag panic.
 - back out holdbkg.go, was too slow.
   add a distinct Holder.imu lock instead.
2020-09-16 09:41:05 -05:00
Kuba Podgórski
dd4ffff704
Merge pull request #853 from kuba--/fix-translate_index_keys
Fix translation index keys
2020-09-16 15:21:31 +02:00
Kuba Podgórski
fa159c9a17
Merge branch 'master' into fix-translate_index_keys 2020-09-16 15:09:49 +02:00
jaten-molecula
47926092ee
Merge pull request #855 from molecula/cleanup_cherrypick
cleanup lmdb tests that were leaving test directories behind
2020-09-16 07:51:23 -04:00
Jason Aten
c093aa9d0e cleanup lmdb tests 2020-09-16 06:46:12 -05:00
Kuba Podgórski
ab26134992
Merge branch 'master' into fix-translate_index_keys 2020-09-16 10:39:32 +02:00
Kuba Podgórski
a8a9a73b6c Fix translation index keys 2020-09-16 10:36:44 +02:00
tgruben
793cf934b8
Merge pull request #848 from molecula/fix_843
don't panic if dbs is reopened under roaring only. fixes #843
2020-09-15 16:54:52 -05:00
Jason Aten
439ac243b4 don't panic if dbs is reopened under roaring only. fixes #843 2020-09-15 15:52:05 -05:00
Kuba Podgórski
e83e18832a
Merge pull request #847 from kuba--/fix-writable
Fix TranslateStore writable
2020-09-15 20:36:27 +02:00
Kuba Podgórski
dcc237413e
Merge branch 'master' into fix-writable 2020-09-15 19:14:24 +02:00
Nia
c7a0b17600
Merge pull request #846 from niaow/typenames
Fix type names in PQL Extract and SQL Show
2020-09-15 13:13:32 -04:00
Kuba Podgórski
76715a3f9d Fix TranslateStore writable 2020-09-15 19:09:59 +02:00
Nia Weiss
19e0f3601b
fix type names in PQL Extract and SQL Show 2020-09-15 12:53:21 -04:00
tgruben
9649819c09
Merge pull request #845 from molecula/rebal_together_rb
fine tune Tx placement, make it lazier so we don't create extra shards.
2020-09-14 18:34:15 -05:00
jaten-molecula
28fa1d036e
Merge branch 'master' into rebal_together_rb 2020-09-14 19:21:31 -04:00
Jason Aten
748f6a61bc fine tune Tx placement, isolate Tx backends more.
- Tx creation is lazier so we don't create xtra shards.

 - Then the dir scan for blue-green state checking finds only the right shards.
2020-09-14 18:03:25 -05:00
Travis Turner
37196b5e03
Merge pull request #834 from travisturner/metric-typos
Fix typos in transaction metric names
2020-09-14 17:32:53 -05:00
Travis Turner
d2c6a8ddde
Merge branch 'master' into metric-typos 2020-09-14 17:20:49 -05:00
seebs
72b1eec2e9
Merge pull request #829 from seebs/storeDistinct
Test cases for Store(Distinct)
2020-09-14 14:28:05 -05:00
Seebs
e7b239d2d8 Test cases for Store(Distinct)
This adds testing for Store(Distinct(...)) with and without filters, to verify that
we can, in fact, store the results of a Distinct() query directly. This was at one
point unsupported, now we think it should work so we're testing it.

The change to the testdata is because the specific structure used for this test doesn't
work with a keyed index, and changing things to be "foreign keys" seems annoying and
more complicated, but possibly that should become part of a future test.

There was talk of testing this with non-BSI fields, but they don't seem to
actually work with Distinct right now, so that will be later.
2020-09-14 14:15:29 -05:00
seebs
88d0f541aa
Merge pull request #841 from seebs/setMapped
export SetMapped from roaring, use it in Tx stores
2020-09-14 14:15:11 -05:00
Seebs
8ab9174a09 export SetMapped from roaring, use it in Tx stores
Thaw() is supposed to always provide writable storage, which it does
by ensuring that containers aren't frozen, but also by cloning or
copying their data if the data is marked as being memory-mapped.

But only the roaring backend had the ability to mark data as memory-mapped,
because that wasn't exported. Fixed this, and added corresponding code
to badger, lmdb, and rbf.
2020-09-14 14:08:00 -05:00
Ben Johnson
343c446b7e
Merge pull request #839 from molecula/rbf-fix-checkpoint
Remove tx before issuing checkpoint.
2020-09-14 12:56:03 -06:00
jaten-molecula
d0ce2e1207
Merge branch 'master' into rbf-fix-checkpoint 2020-09-14 13:58:24 -04:00
alanbernstein
1e40af7e25
Merge pull request #830 from alanbernstein/metrics-json-fix
Fix panicking metrics.json endpoint
2020-09-14 12:28:39 -05:00
Ben Johnson
77661a891d Remove tx before issuing checkpoint. 2020-09-14 10:36:59 -06:00
Alan Bernstein
18a593008a Add simple tests for metrics endpoints 2020-09-14 11:34:59 -05:00
Alan Bernstein
acbd6ec37c New channel per node 2020-09-14 11:34:59 -05:00
jaten-molecula
fc2518e2d1
Merge pull request #838 from molecula/fix_rr_leaks
fix TestImportClearRestart resource leaks under roaring, better skipForRoaring func
2020-09-14 11:38:26 -04:00
Jason Aten
7028bcfc9d fix resource leaks in fragment_internal_test.go under roaring, better skipForRoaring func
- add tournament.sh to do all pair-wise comparisons of blue-green backends.
- isolate txstores away from roaring index/ directories with indexname.index.txstores@@@ dirs.
2020-09-13 22:45:39 -05:00
Travis Turner
a0db828701
Merge pull request #835 from travisturner/port-vdsm-metrics
Port over VDSM metrics
2020-09-11 16:28:36 -05:00
Travis
41e0465eda
Port over VDSM metrics 2020-09-11 16:03:50 -05:00
Travis
75644af64d
Fix typos in transaction metric names 2020-09-11 15:18:39 -05:00
tgruben
5e00dbadc2
Merge pull request #812 from molecula/bgdev_rb
blue_green migration; holdbkg.go holder goroutine.
2020-09-11 14:32:09 -05:00
Jason Aten
2eb097c14d blue_green migration. holdbkg.go holder goroutine.
- blue_green for doing migration. Called before Holder.Open finishes.
- holdbkg.go added for index lookup. Less wedging between a deadlock and a race.
- fix fault under read-only map under lmdb at
  TestExecutor_Execute_Row_Range/RowIDColumnID by doing cow in roaring.
- roaring -tags gofuzz builds again
- roaringparanoia build tag added to make test targets in Makefile
- add rbf.NewDBWithAllocZero for out-of-bounds memory checks
- .circleci/config.yml test-shardwidth-22 with large run container, kept OOM-ing we suspect.

Fixes #819
2020-09-11 14:24:15 -05:00
Antonio Navarro Perez
a68ee73f00
Merge pull request #782 from ajnavarro/remove-blake3-duplicated-code 2020-09-11 11:23:25 +02:00
jaten-molecula
2cc7c829cd
Merge branch 'master' into remove-blake3-duplicated-code 2020-09-11 01:14:02 -04:00
Ben Johnson
5b72a68628 Stack allocate return from rbf.Tx.cursor() 2020-09-10 14:58:22 -06:00
Nia
be944a6247
Merge pull request #822 from niaow/inspect-panic
Fix inspect panic from incorrect handling of the many types of empty argument
2020-09-09 09:39:20 -04:00
Nia Weiss
6ff224308d
fix inspect panic from incorrect handling of the many types of empty argument 2020-09-09 09:11:21 -04:00
seebs
db578423bb
Merge pull request #818 from seebs/roaringDoc
Roaring documentation updates and fixes resulting from them
2020-09-08 22:41:48 -05:00
Seebs
c079d4764b Check for possibly-dirty N values in containers modified in-place
After documenting the semantics, I noticed an arguable hole in them,
which is that you could Freeze() a dirty container, and then Repair()
wouldn't work on it. On further study, I added a roaringparanoia
check for attempts to access the N of dirty containers.

It turns out there's several such. But also, it turns out, there's
circumstances where unionInPlace is relying on the assumption that
N is valid, which it isn't always for dirty containers. Also, there's
at least one case where we rely on the assumption that forcibly
thawing a container, then calling unionInPlace on it, always modifies
that container. But that's not supposed to be true for an empty
container -- an empty container might be better handled by just
returning the container it's being unioned with. So, we drop the
unnecessary thaw (all the *InPlace ops are already thawing if/when
they need to), but we use the return from unionInPlace.
2020-09-08 13:16:54 -05:00
Seebs
17ba2e35a9 call helper functions every time to get new run slices
If you just stash the results of the function when defining the test cases, the
outcome is in part that you are reusing the same slices for multiple things. So,
for instance, if you perform a union on the OddBitsSet slice, with the EvenBitsSet
slice, the result is to overwrite the first entry in that slice with the 0-ffff
run... But the original slice still exists, and then we reuse it and get a slice
with a bit count of around 98,000. The underlying issue is that doContainer()
is calling NewContainerRun(), which is simply using the provided slice, not
copying it -- which is intentional, but the test has to be careful about it.

We call repair on the one we think should be a bitmap. Theoretically
maybe we should also repair the other one in case unionRunRun some day
starts returning unrepaired bitmaps, which in principle it's allowed to
do...
2020-09-08 12:38:49 -05:00
Seebs
ecacbf65d4 Document copy-on-write semantics, at all.
The copy-on-write semantics were previously documented only in
the 125-line commit log from the patch which introduced them. Add
documentation for them in a few likely places.
2020-09-08 11:44:56 -05:00
Ben Johnson
8397696a59
Merge pull request #813 from molecula/import-roaring-direct
Add direct import option; remove tx from fragment.Open()
2020-09-08 08:19:24 -06:00
Ben Johnson
a51c530763 Add direct import option; remove tx from fragment.Open() 2020-09-08 08:13:16 -06:00
Ben Johnson
62635e7668
Merge pull request #811 from molecula/fix-wal-replay
Fix RBF WAL replay/truncation
2020-09-08 08:11:00 -06:00
Ben Johnson
f2bde49d25 Fix RBF WAL replay/truncation 2020-09-07 09:39:26 -06:00
Antonio Navarro Perez
ca340f7e62 [hash] Remove duplicated blake3 code
blake3 code is used in several places on the code. The file was
duplicated on root and rbf package.

To avoid cyclic dependencies, I moved it to hash package. Some methods
must be public to use them in different places.

HashOfDir method was removed. Not used.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2020-09-07 12:24:22 +02:00
jaten-molecula
1994560cf6
Merge pull request #803 from molecula/fgen_refined
refine our f.gen nil handling to support blue/green
2020-09-04 18:52:32 -04:00
Jason Aten
63187f59ee refine our f.gen nil handling to support blue/green 2020-09-04 17:28:38 -05:00
Ben Johnson
278d518f03
Merge pull request #800 from molecula/rbf-exclusive-write
Add RBF exclusive lock mode
2020-09-04 13:41:52 -06:00
Ben Johnson
90663e070e
Merge branch 'master' into rbf-exclusive-write 2020-09-04 13:10:02 -06:00
jaten-molecula
bb101ebef2
Merge pull request #802 from molecula/fgen
restore former f.gen nil behavior
2020-09-04 14:56:45 -04:00
Ben Johnson
159d01b55d Add exclusive write option for RBF.
This commit adds the ability to start a transaction with an exclusive
lock for the entire database. This ensures no other read or write
transactions can run at the same time. Writes in this mode write
directly to the database and skip the WAL entirely.
2020-09-04 12:46:42 -06:00
Jason Aten
4b6e773c7c panic if f.gen is nil because it means the storage wasn't open 2020-09-04 13:19:46 -05:00
jaten-molecula
aebe028854
Merge pull request #777 from molecula/dbshard2
database per shard, HolderConfig, rbf bit-wise import speedups.
2020-09-04 14:04:13 -04:00
Ben Johnson
150c8a5b06 database per shard, HolderConfig, rbf bit-wise import speedups.
- introduce Query Context (Qcx) for managing database-per-shard.
- replaces the MultiTx, so mtx.go is retired and removed.
- introduces the HolderConfig struct and all Holders now have
  a path from birth.
- rbf speedups on bitwise writes
- badgerdb is removed due to unresolvable write conflicts.

fixes #703 #676
2020-09-04 13:00:33 -05:00
Nia
60da12a8e5
Merge pull request #784 from niaow/remove-sql-limit
Remove SQL artificial limit
2020-09-04 08:46:33 -04:00
Nia
ec41481523
Merge branch 'master' into remove-sql-limit 2020-09-04 08:11:48 -04:00
jaten-molecula
921f15991b
Merge pull request #788 from molecula/fldschk
pilosa-chk: show col, row translation, -v for fragment details
2020-09-03 19:20:11 -04:00
Jason Aten
1e87d113f1 pilosa-chk: col, row translation reported, -v shows fragment checksum 2020-09-03 18:14:49 -05:00
tgruben
17ddcacbd4
Merge pull request #787 from molecula/chktrans
cmd/translatorchk checksums and summarizes key counts from column key translators
2020-09-03 15:29:31 -05:00
Jason Aten
56803e6632 pilosa/cmd/translatorchk checksums and summarizes key counts from column key translators.
opens ~/.pilosa/index/_keys boltdbs and hashes the StringKey->ID mappings.
2020-09-03 15:23:05 -05:00
Nia Weiss
b676292d67
add named returns to clarify extractLimitOffset 2020-09-03 10:37:09 -04:00
Nia Weiss
daa784319c
remove SQL artificial limit 2020-09-03 09:14:11 -04:00
jaten-molecula
d3485dbdb3
Merge pull request #776 from niaow/configure-slurp
Configure slurp
2020-09-03 02:33:58 -04:00
jaten-molecula
0a548a9009
Merge branch 'master' into configure-slurp 2020-09-03 01:56:30 -04:00
Nia
82e5f09cb3
Merge pull request #779 from niaow/pg-race
Fix race condition in pg cancellation test
2020-09-02 19:07:28 -04:00
Nia Weiss
c9995bfae1
fix race condition in pg cancellation test 2020-09-02 19:01:47 -04:00
Nia
bd1b76e25e
Merge pull request #760 from niaow/pg-local-cancel
Add support for local cancellation to postgres endpoint
2020-09-02 15:05:31 -04:00
Nia
219e22cc64
Merge branch 'master' into pg-local-cancel 2020-09-02 14:02:18 -04:00
Nia Weiss
95d261b4d7
configure slurp 2020-09-02 12:53:16 -04:00
jaten-molecula
c213cb5457
Merge pull request #762 from molecula/optimize-import
rbf bitwise import optimizations
2020-09-01 21:44:46 -04:00
jaten-molecula
55cb448c37
Merge branch 'master' into optimize-import 2020-09-01 21:18:57 -04:00
Travis Turner
836d055978
Merge pull request #759 from travisturner/join-bug
fix bug on left/right join mapping
2020-09-01 19:06:49 -05:00
Kuba Podgórski
6255c3f07f
Merge branch 'master' into join-bug 2020-09-02 01:51:48 +02:00
Travis Turner
72c068a64f
Merge pull request #773 from travisturner/row-pointer
return *Row instead of Row on empty key result
2020-09-01 18:31:29 -05:00
Travis
32b5826d1a
fix bug on left/right join mapping 2020-09-01 18:22:55 -05:00
Travis
d02cb10687
return *Row instead of Row on empty key result 2020-09-01 17:34:29 -05:00
alanbernstein
58007ab7ef
Merge pull request #765 from alanbernstein/lattice-release
Add embedded UI to default release process
2020-09-01 13:27:08 -05:00
Alan Bernstein
007b3ffc3c re-re-arrange error checks 2020-09-01 11:32:58 -05:00
Alan Bernstein
4ce3879e2c Revert UI->Lattice name change, correct the ordering of error checks in statikHandler 2020-09-01 10:16:31 -05:00
Alan Bernstein
a597a79e2d Add embedded UI to default release process 2020-09-01 10:16:31 -05:00
Kuba Podgórski
2d202d6aa3
Merge pull request #766 from kuba--/fix-null
support null results
2020-09-01 15:33:02 +02:00
Kuba Podgórski
ceb72fc3a9 support null results 2020-09-01 13:00:30 +02:00
Nia
1e5f0ecc5d
Merge pull request #763 from niaow/sql-leak
Fix SQL memory leak
2020-08-31 14:38:23 -04:00
Nia Weiss
d421558f58
fix SQL memory leak 2020-08-31 13:10:49 -04:00
Nia
96a8fd5cb7
Merge pull request #724 from niaow/pg-primitive
Add primitive types to pg encoder
2020-08-31 13:04:39 -04:00
Nia Weiss
9f368b06bd
add licesnse header to pg formatter test 2020-08-31 12:42:37 -04:00
Nia Weiss
542eb2dba3
pg formatter tests 2020-08-31 12:39:55 -04:00
Nia Weiss
cfcc1da0bb
add primitive types to pg encoder 2020-08-31 12:27:10 -04:00
Nia
9b12c01c2b
Merge pull request #736 from niaow/dirtycache
Force ranked cache recalculation in Top after a skipped invalidation
2020-08-31 11:56:50 -04:00
Nia
ac57a0bd42
Merge branch 'master' into dirtycache 2020-08-31 11:28:52 -04:00
Ben Johnson
1672158e65
Merge branch 'master' into optimize-import 2020-08-31 08:58:12 -06:00
Ben Johnson
627b50d89d misc import optimizations 2020-08-31 08:46:53 -06:00
alanbernstein
b2cad11c99
Merge pull request #733 from alanbernstein/enlattice
Embed lattice via statik
2020-08-31 09:40:02 -05:00
Alan Bernstein
b14ebcadae Unexport statik filesystem 2020-08-31 09:02:46 -05:00
Cody Soyland
a3e122dc5e Fix CORS support by applying middleware to router. 2020-08-31 09:02:46 -05:00
Alan Bernstein
f9d3040827 Update gitignore and makefile 2020-08-31 09:02:46 -05:00
Alan Bernstein
384b6511cd Replace null with [] in /schema field response 2020-08-31 09:02:46 -05:00
Alan Bernstein
659a2bb560 Silence stderr in makefile 2020-08-31 09:02:46 -05:00
Alan Bernstein
6e917b6a9a Log lattice version info 2020-08-31 09:02:46 -05:00
Alan Bernstein
99869ce792 Minor fixes 2020-08-31 09:02:46 -05:00
Alan Bernstein
b039bd50a1 Switch to mux PathPrefix matcher entirely 2020-08-31 09:02:46 -05:00
Alan Bernstein
19ee27fdb6 Use SPA handler to serve from filesystem, to test routing behavior 2020-08-31 09:02:46 -05:00
Alan Bernstein
d912403eb2 Add missing file 2020-08-31 09:02:46 -05:00
Alan Bernstein
88a288e775 Embed lattice via statik 2020-08-31 09:02:46 -05:00
Kuba Podgórski
b88c5cd5ea
Merge pull request #753 from kuba--/grpc-errcode
Add rich error types to gRPC interface
2020-08-31 15:45:24 +02:00
Kuba Podgórski
bfff643f34 Fix error code for PostVDS 2020-08-31 12:16:07 +02:00
Kuba Podgórski
f7a0e5f536 Fix error code for DeleteVDS 2020-08-31 12:14:58 +02:00
Kuba Podgórski
bf17385409
Merge branch 'master' into grpc-errcode 2020-08-31 10:25:35 +02:00
Nia Weiss
bf7e4b5583
add support for local cancellation to postgres endpoint 2020-08-29 14:56:49 -04:00
Nia
9c0d45a2d9
Merge pull request #752 from niaow/batch-translate
Batch the translation of field keys in results
2020-08-28 15:25:19 -04:00
Nia
5bc5991bd7
Merge branch 'master' into batch-translate 2020-08-28 15:09:05 -04:00
Kuba Podgórski
25ead95967
Merge branch 'master' into grpc-errcode 2020-08-28 20:42:28 +02:00
Nia Weiss
8549b74421
merge groupcount translations check into an else-if 2020-08-28 14:22:35 -04:00
Nia
a872548b01
Merge pull request #756 from niaow/postgres-sql-empty
Write empty column headers in postgres when there is no response
2020-08-28 14:20:22 -04:00
Nia Weiss
57fdabfe40
write empty column headers in postgres when there is no response 2020-08-28 13:28:50 -04:00
Travis Turner
81d32a6eeb
Merge pull request #751 from travisturner/sql-mapper-stuff
add sql mapper routes for count(*) on joins
2020-08-28 11:55:49 -05:00
Travis Turner
27c2368b9a
Merge branch 'master' into sql-mapper-stuff 2020-08-28 11:43:16 -05:00
Nia Weiss
0a9699490b
batch the translation of field keys in results 2020-08-28 11:56:37 -04:00
Kuba Podgórski
2b1c9950f4 Add rich error types to gRPC interface 2020-08-28 17:24:49 +02:00
jaten-molecula
f2fb2c98f8
Merge pull request #737 from molecula/bulk-import-value
Implement TxBitmap to cache up many bit changes in a Tx
2020-08-28 00:43:46 -04:00
Travis
ae07aacd51
add sql mapper routes for count(*) on joins 2020-08-27 22:49:54 -05:00
jaten-molecula
4883424205
Merge branch 'master' into bulk-import-value 2020-08-27 21:43:32 -04:00
Nia
9c621d7622
Merge pull request #742 from niaow/pg-require-tls
Fix postgres configuration
2020-08-27 12:49:45 -04:00
Nia Weiss
f0f8336f57
rename postgres.addr to postgres.bind for consistency 2020-08-27 11:35:54 -04:00
Ben Johnson
e3db6c9cec Implement bulk value import 2020-08-27 09:20:23 -06:00
Nia Weiss
68542ddc35
force ranked cache recalculation in Top after a skipped invalidation 2020-08-27 11:05:18 -04:00
Nia Weiss
288593231f
require TLS when configured 2020-08-27 10:59:40 -04:00
Nia Weiss
47dd6b5b8f
fix postgres endpoint config 2020-08-27 10:49:43 -04:00
Nia Weiss
c2823a933b
add a config option to require TLS on postgres 2020-08-27 10:49:43 -04:00
Kuba Podgórski
475a9e3910
Merge pull request #732 from kuba--/translatekey-writable
Add writable argument to TranslateKey functions.
2020-08-27 16:15:49 +02:00
Kuba Podgórski
248ec3a296
Merge branch 'master' into translatekey-writable 2020-08-27 16:10:29 +02:00
Kuba Podgórski
6b9eed3af4
Merge pull request #743 from kuba--/fix-info
Pass name to newNotFoundError
2020-08-27 16:08:40 +02:00
Kuba Podgórski
2ca8ca0605 Pass name to newNotFoundError 2020-08-27 15:35:23 +02:00
Nia
c3174efdeb
Merge pull request #740 from niaow/xor-array-array
Speed up xorArrayArray
2020-08-26 17:30:57 -04:00
Nia Weiss
6e06cc0c30
speed up xorArrayArray 2020-08-26 17:14:24 -04:00
Kuba Podgórski
9cf58ddb1c Add writable argument to TranslateKey functions. 2020-08-26 09:57:50 +02:00
Kuba Podgórski
ca5e27ad8e
Merge pull request #721 from kuba--/invalid-query/fix-706
Fix https://github.com/molecula/pilosa/issues/706
2020-08-25 21:33:54 +02:00
Kuba Podgórski
b67148ccfc
Merge branch 'master' into invalid-query/fix-706 2020-08-25 20:38:30 +02:00
Nia
6db4c8bb3a
Merge pull request #725 from niaow/storekeyed
Fix Store() into a keyed set
2020-08-25 14:08:46 -04:00
Kuba Podgórski
24980c7af8
Merge branch 'master' into invalid-query/fix-706 2020-08-25 19:30:03 +02:00
Nia Weiss
a8e7c2d0ef
fix Store() into a keyed set 2020-08-25 11:39:03 -04:00
jaten-molecula
8ad3dd2de6
Merge pull request #728 from molecula/skip_cluster_tests_bg
TestClusterResize_AddNode,AddNodeConcurrentIndex skipped blue-green roaring
2020-08-25 04:06:49 -04:00
tgruben
06281fc0c8
Merge branch 'master' into skip_cluster_tests_bg 2020-08-25 02:30:00 -05:00
tgruben
15315e47ee
Merge pull request #729 from molecula/fix683
test roaring.Container.UnionInPlace does not overflow
2020-08-25 02:29:29 -05:00
jaten-molecula
bc18e4dc42
Merge branch 'master' into skip_cluster_tests_bg 2020-08-25 03:28:00 -04:00
Jason Aten
ca7552b4a8 test that roaring.Container.UnionInPlace does
not overflow two big arrays into an invalid array.

recreate badloader from git history, at 85fa67e8. Could not
reproduce this, but lots of container usage
also got updated in the meantime.

Fixes #683
2020-08-24 17:06:41 -05:00
jaten-molecula
c5660ed712
Merge pull request #701 from molecula/fix-rbf-race
Remove duplicate checkpoint() invocation
2020-08-24 16:19:20 -04:00
jaten-molecula
ec02d5a00e
Merge branch 'master' into fix-rbf-race 2020-08-24 16:06:25 -04:00
jaten-molecula
0e6b65d3c2
Merge branch 'master' into skip_cluster_tests_bg 2020-08-24 16:02:13 -04:00
Jason Aten
48f31ddce7 TestClusterResize_AddNode and TestClusterResize_AddNodeConcurrentIndex skipped under blue-green test with roaring 2020-08-24 14:57:08 -05:00
alanbernstein
14a9a838eb
Merge pull request #690 from alanbernstein/prometheus-json
Add metrics.json endpoint using prometheus/prom2json
2020-08-24 14:29:27 -05:00
Alan Bernstein
9b027a89b9 Return dict of all node metrics 2020-08-24 14:04:02 -05:00
Alan Bernstein
d9b670c83c Add metrics.json endpoint using prometheus/prom2json 2020-08-24 14:04:02 -05:00
Sarah
6c4e8aeff5
Merge branch 'master' into fix-rbf-race 2020-08-24 13:23:56 -05:00
jaten-molecula
0e4144c302
Merge pull request #709 from molecula/audit3rb
testhook: Leak auditing infrastructure
2020-08-24 12:32:20 -04:00
Seebs
cecaf99ee4 testhook: leak auditing infrastructure
The testhook/ package provides an easy way to set up multiple
hooks to run before/after tests are run.

The audit hooks track open and closes of storage backends,
files, indexes, and holders, for example. A tempdir wrapper
creates temporary directories which are automatically cleaned up
when the test ends. Any kind of resource creation that
should be closed at test conclusion can be tracked. We
will complain at the end of the TestMain if resources are
leaking.

Leaks under go1.13:

We use a wrapper function which is a no-op for go 1.13, but actually
calls testing.TB.Cleanup in go1.14, so we can still build with 1.13 even though
tests will leak files all over the place there. Because of this,
don't run the testhook tests when using 1.13, as they'll always fail.

- the test/pilosa.go http client now times out after 10 seconds
to help diagnose hung server situations.

- Makefile targets added to get better progress reports.
2020-08-24 11:26:39 -05:00
jaten-molecula
7e326fb833
Merge pull request #722 from tgruben/rbf-add
copied optimized add/remove to rbf
2020-08-24 11:42:57 -04:00
Todd Gruben
edf6608129 copied optimized add/remove to rbf
use large test container for CI
2020-08-24 10:37:25 -05:00
Kuba Podgórski
397d37a129 Fix https://github.com/molecula/pilosa/issues/706 2020-08-24 15:34:09 +02:00
Kuba Podgórski
bc3f329e8f
Merge pull request #720 from kuba--/sql-drop
Add support for SQL 'drop table...'
2020-08-24 14:52:49 +02:00
Kuba Podgórski
ceda4ab61b Add support for drop table 2020-08-24 13:24:18 +02:00
tgruben
9caa670c90
Merge pull request #719 from tgruben/lmdb-add
copied badger addRemove implementation to lmdb
2020-08-23 08:50:07 -05:00
tgruben
9e94c86932
Merge branch 'master' into lmdb-add 2020-08-23 08:40:16 -05:00
Todd Gruben
4dd4b441c4 copied badger addRemove implementation to lmdb 2020-08-23 08:39:03 -05:00
jaten-molecula
4a6d8bc5df
Merge branch 'master' into fix-rbf-race 2020-08-22 23:23:57 -04:00
Nia
0ce9062588
Merge pull request #716 from kuba--/sql-show
Add support for SHOW queries
2020-08-21 19:46:47 -04:00
Kuba Podgórski
ad9e3338b5 Add support for SHOW queries 2020-08-22 01:25:35 +02:00
Nia
c137efbe44
Merge pull request #707 from niaow/pg-sql
Add SQL to postgres endpoint
2020-08-21 19:13:26 -04:00
Kuba Podgórski
cb89a4a831
Merge branch 'master' into pg-sql 2020-08-22 01:01:22 +02:00
Kuba Podgórski
37a4cda454
Merge pull request #563 from kuba--/fix-210/translate-entry
Fix 210/translate entry
2020-08-22 00:52:53 +02:00
Kuba Podgórski
7c13fa71d7
Merge branch 'master' into fix-210/translate-entry 2020-08-22 00:18:34 +02:00
Kuba Podgórski
6d0baa82b3
Update http/translator_test.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-08-22 00:18:25 +02:00
Kuba Podgórski
cc66775ea4
Update http/translator_test.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-08-22 00:18:19 +02:00
Nia
842377ba17
Merge pull request #713 from niaow/dont-log-100000-times
Stop logging in TestStartupInvalidLength
2020-08-21 17:29:52 -04:00
Nia Weiss
dd73bf3960
stop logging in TestStartupInvalidLength 2020-08-21 17:20:10 -04:00
jaten-molecula
8d397babdf
Merge pull request #710 from molecula/clear_importvals
ImportRequest.Clear and ImportValuesRequest.Clear respected by api.Import() and api.ImportValues()
2020-08-21 15:42:24 -05:00
tgruben
056d5990da
Merge branch 'master' into clear_importvals 2020-08-21 15:33:04 -05:00
Jason Aten
40a9d01f46 ImportRequest.Clear and ImportValuesRequest.Clear respected by api.Import() and api.ImportValues()
- tested in TestAPI_ClearFlagForImportAndImportValues api_test.go
2020-08-21 15:17:44 -05:00
Nia Weiss
49c3bd9701
add SQL to postgres endpoint 2020-08-21 14:47:59 -04:00
Ben Johnson
91c8c5b5e9
Merge branch 'master' into fix-rbf-race 2020-08-21 10:33:43 -06:00
Kuba Podgórski
a2f24bc115
Merge pull request #663 from kuba--/sql-mapper
SQL mapper
2020-08-21 17:24:59 +02:00
Ben Johnson
162bd0303a Remove duplicate checkpoint() invocation 2020-08-21 08:25:04 -06:00
Kuba Podgórski
17fa1e578b Add benchmark for translation reader 2020-08-21 15:15:41 +02:00
Kuba Podgórski
bbbeb22d31
Merge branch 'master' into sql-mapper 2020-08-21 03:17:46 +02:00
tgruben
57babb3269
Merge pull request #700 from molecula/atomicrecord
AtomicRecord allows the client to request atomic updates.
2020-08-20 17:42:15 -05:00
Jason Aten
df5dd1557e AtomicRecord allows the client to request atomic updates.
- Atomic record contains multiple ImportRequest and
   ImportValueRequest, plus ability to Clear individual requests.
 - adds http handlers for importing AtomicRecord.
2020-08-20 17:33:52 -05:00
Kuba Podgórski
0e0a405184
Merge branch 'master' into sql-mapper 2020-08-20 21:53:59 +02:00
Nia
272f6708a3
Merge pull request #679 from niaow/pg
Add a postgres endpoint to pilosa
2020-08-20 14:24:56 -04:00
Kuba Podgórski
6fa69fb81a
Merge branch 'master' into sql-mapper 2020-08-20 20:17:53 +02:00
Nia Weiss
14676c0713
remove postgres debugging types 2020-08-20 14:17:50 -04:00
Nia
44061923c7
Update pg/message/io.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-08-20 14:14:14 -04:00
Nia Weiss
128e02046a
add a postgres endpoint to pilosa 2020-08-20 11:29:16 -04:00
alanbernstein
68b17312e0
Merge pull request #687 from alanbernstein/unicode
Use _buffer instead of buffer
2020-08-19 17:12:26 -05:00
Alan Bernstein
6fc5465aaa Use rune slice in all cases, add tests 2020-08-19 16:32:27 -05:00
Alan Bernstein
0a96043c23 Use _buffer instead of buffer 2020-08-19 16:32:27 -05:00
Kuba Podgórski
0be436e18d
Merge branch 'master' into sql-mapper 2020-08-19 21:33:58 +02:00
Ben Johnson
0a37f396f8
Merge pull request #671 from molecula/wal-write-cache
Add RBF WAL write cache
2020-08-19 09:54:55 -06:00
Ben Johnson
9dbb82cf3e WAL mutex fixes 2020-08-19 08:42:53 -06:00
Ben Johnson
51504f4fe4 Add WAL write cache mutex; update name; add benchmarks 2020-08-19 08:33:19 -06:00
Ben Johnson
5849794a1b Add RBF WAL write cache 2020-08-19 08:33:19 -06:00
Cody Soyland
776de471db
Merge pull request #693 from molecula/ubuntu_dockerfile
ubuntu 20:10 image instead of alpine, for cgo support
2020-08-18 20:40:26 -05:00
Jason Aten
ef156f6172 ubuntu 20:10 image instead of alpine, for cgo support 2020-08-18 16:55:44 -05:00
Kuba Podgórski
2b34976c22 porting sqlmapper from vdsm 2020-08-18 15:53:26 +02:00
Cody Soyland
039780a85e
Merge pull request #685 from molecula/discard-test-386
no more test-386
2020-08-17 20:15:14 -05:00
Jason Aten
aea7d4a812 no more test-386
- lmdb won't build under 386
 - still have to keep lmdb_other.go for arm/arm64
2020-08-17 19:54:50 -05:00
jaten-molecula
ba1d5e9f9f
Merge pull request #681 from molecula/fix-rbf-reopen
Fix RBF checkpoint on reopen. Fixes #673
2020-08-17 19:16:17 -05:00
jaten-molecula
3e4da916e8
Merge branch 'master' into fix-rbf-reopen 2020-08-17 19:09:55 -05:00
tgruben
d84ae88944
Merge pull request #677 from molecula/lmdb_as_backend
add lmdb, Tx call stats, and prep for db/shard.
2020-08-17 18:43:57 -05:00
Jason Aten
123ce41840 add lmdb, Tx call stats, and prep for db/shard.
- lmdb as a backend (lmdb.go)
   (lmdb is the fastest known transactional storage backend)
 - per Tx call statics report enabled with PILOSA_CALLSTAT=true (stattx.go)
 - framework for per-shard db (dbshard.go)
 - txfactory handles any pair under blue-green testing (txfactory.go)
 - enable CGO in Dockerfiles for lmdb
2020-08-17 18:26:58 -05:00
seebs
4f7e4feaf8
Merge pull request #680 from seebs/cachefix
when updating a container, drop the single-container cache
2020-08-17 15:03:10 -05:00
Ben Johnson
b1e806a518 Fix RBF checkpoint on reopen.
Previously, the `rbf.DB.opened` flag was set after `checkpoint()`
when reopening, however, this flag is checked by `checkpoint()` so
it was not properly executing.
2020-08-17 13:28:28 -06:00
Seebs
16ba54293a when updating a container, drop the single-container cache
This can cause incredibly weird and hard-to-debug problems if the previous
container value is still in the cache after an update, and in particular,
can result in having a stale container value cached after a roaring import
that modified the container. Coupled with another bug which could corrupt
containers on a delete, this produces a very strange bug where a value is
present in a fragment, but an attempt to delete it reports failure.
2020-08-17 11:23:47 -05:00
Travis Turner
c5e9b8d917
Merge pull request #674 from travisturner/container-corrupt
stop setting N on a frozen container
2020-08-16 15:59:58 -05:00
Travis
ff5925aa8b
stop setting N on a frozen container 2020-08-14 17:25:14 -05:00
Matthew Jaffee
cd83f7965c
Merge pull request #672 from molecula/remove-transaction.md
remove old transactions doc
2020-08-14 14:40:10 -05:00
Matt Jaffee
b11bdeab87
remove old transactions doc 2020-08-14 11:57:28 -05:00
jaten-molecula
05ca83c2f5
Merge pull request #669 from molecula/autocommit2
build-tag out lmdb-go from builds; lower autocommit limits to avoid ErrTxnTooBig; improve txn size estimation
2020-08-13 11:52:42 -05:00
Jason Aten
c90c4c275d lower autocommit limits to avoid ErrTxnTooBig; improve txn size estimation 2020-08-13 16:42:47 +00:00
Travis Turner
1f53e86e47
Merge pull request #662 from travisturner/transaction-list
transactions as a list endpoint; added Transaction.CreatedAt
2020-08-13 08:40:57 -05:00
Travis
1837811ce1
transactions as a list endpoint; added Transaction.CreatedAt 2020-08-12 23:11:54 -05:00
tgruben
0dea018fb7
Merge pull request #665 from molecula/autocommit
tested working autocommit approach
2020-08-12 21:56:03 -05:00
Jason Aten
5e49e10cda tested working autocommit approach 2020-08-13 01:12:14 +00:00
jaten-molecula
c7d6229380
Merge pull request #664 from molecula/bigtx
PutContainer() handles large txn with autocommit
2020-08-12 19:18:19 -05:00
Jason Aten
6dc9727796 PutContainer() handles large txn with autocommit 2020-08-12 23:15:23 +00:00
jaten-molecula
973e9a7955
Merge pull request #659 from molecula/rbf_99pct
all test green on rbf. WOOT.
2020-08-12 16:13:47 -05:00
Todd Gruben
547ee14f5b all test green on rbf. WOOT.
- rbf had races around the new rootRecords cache in tx
 - rbf tx needed a write lock on the db now that rootRecords are written
 - added a global registry for rbfDB to correctly dedup instances
 - implement DeleteFragment, DeleteIndex for rbf
 - use badger style keys for rbf to allow content checksumming to be list
    containers in the same order
 - lots of other integration of rbf into pilosa layer.
2020-08-12 21:08:30 +00:00
Cody Soyland
123e0b6376
Merge pull request #644 from codysoyland/grpc-crd-sql
Add gRPC methods to support the functionality of VDSM
2020-08-12 14:55:24 -05:00
Cody Soyland
21456827ae
Merge branch 'master' into grpc-crd-sql 2020-08-12 14:21:53 -05:00
Cody Soyland
3361033c5b Add PostVDS and DeleteVDS 2020-08-12 14:21:22 -05:00
Cody Soyland
3771bd43b5 Add note about gRPC unary methods and futures 2020-08-12 14:08:30 -05:00
Nia
50a2e3c5fa
Merge pull request #650 from jaddr2line/limit
Add a "Limit" query
2020-08-12 14:04:12 -04:00
Nia
911c039991
Fix incorrect negative in Limit query documentation
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-08-12 13:53:57 -04:00
Jaden Weiss
40a6fbd79e
add a "Limit" query 2020-08-12 12:27:23 -04:00
Nia
2a1fafb227
Merge pull request #652 from jaddr2line/constrow
Add ConstRow query
2020-08-12 12:22:06 -04:00
Nia
a19ca16810
Merge branch 'master' into constrow 2020-08-12 11:47:46 -04:00
Travis Turner
683b8dfe31
Merge pull request #660 from travisturner/error-rows-int
error on Rows(field=<int>)
2020-08-11 19:44:46 -05:00
Travis
eae038a07e
error on Rows(field=<int>) 2020-08-11 18:07:03 -05:00
Jaden Weiss
0e16192aeb
add ConstRow query 2020-08-11 08:25:32 -04:00
Jaden Weiss
96c2364c1b
Merge pull request #642 from jaddr2line/query-extract
Add an "Extract" query
2020-08-10 19:32:36 -04:00
Jaden Weiss
590bd07995
add an "Extract" query 2020-08-10 09:33:55 -04:00
Cody Soyland
559a2c6864 Add GetVDS and GetVDSs gRPC implementations 2020-08-07 16:28:06 -05:00
Ben Johnson
2bc3442ae8
Merge pull request #649 from molecula/fix-rbf-rollback
Fix RBF checkpoint high water mark
2020-08-07 14:29:31 -06:00
Ben Johnson
faa1662bf6 Fix RBF checkpoint high water mark
Previously, the `checkpoint()` function determined the segments to drop
based on the current active transactions' WAL ID references. However, if
no transactions are active then the checkpoint would drop segments too
aggressively.

This changes the determination by using the highest WAL ID that is
actually checkpointed to disk to determine the high water mark. If no
page are checkpointed then no segments can be dropped.
2020-08-07 10:07:33 -06:00
Ben Johnson
5644867507
Merge pull request #643 from molecula/fix-rbf-hanging-tests
Fix RBF/pilosa hanging tests
2020-08-07 10:06:57 -06:00
Cody Soyland
35675a3e59 Add stubbed gRPC types to support python-molecula
This adds the following rpc calls: GetVDS, GetVDSs, PostVDS, DeleteVDS, QuerySQL, QuerySQLUnary

Currently, they are not implemented.
2020-08-06 14:19:16 -05:00
Ben Johnson
78f9fbe332 Fix RBF/pilosa hanging tests 2020-08-06 11:43:41 -06:00
alanbernstein
5306426b19
Merge pull request #641 from alanbernstein/more-docs-updates
Fix various docs issues
2020-08-05 12:34:57 -05:00
Alan Bernstein
5f26290f92 Fix various docs issues 2020-08-05 12:26:22 -05:00
Ben Johnson
3fb2cccb00
Merge pull request #637 from molecula/rbf-fixes
Multiple RBF test fixes
2020-08-05 09:02:06 -06:00
Ben Johnson
f8cacd8081 Multiple RBF test fixes 2020-08-05 08:20:34 -06:00
Travis Turner
df709af10e
Merge pull request #638 from travisturner/fix-executeclearrow
safe cast of bool in executeClearRow
2020-08-04 15:52:48 -05:00
Travis
ddee2cb0a8
safe cast of bool in executeClearRow 2020-08-04 15:16:23 -05:00
tgruben
7f6c6956d8
Merge pull request #635 from molecula/efence_off
DetectMemAccessPastTx flag added, default false.
2020-08-03 22:03:36 -05:00
tgruben
86b5d89bc9
Merge branch 'master' into efence_off 2020-08-03 21:24:23 -05:00
alanbernstein
dede69f04d
Merge pull request #590 from alanbernstein/improve-tx-error-messages
Improve 'shouldn't ever happen' error messages
2020-08-03 12:44:30 -05:00
alanbernstein
27edff60b0
Merge branch 'master' into improve-tx-error-messages 2020-08-03 12:34:22 -05:00
Jason Aten
b806322c5a DetectMemAccessPastTx flag added, default false. Allow badger to run at full speed rather than with debugging code on by default 2020-08-01 21:40:54 -04:00
tgruben
0820babc44
Merge pull request #634 from molecula/unionfix
Follow roaring.Union() with optimize() to avoid overly large containers.
2020-08-01 08:58:47 -05:00
Jason Aten
394b8522d1 Follow roaring.Union() with optimize() to avoid overly large containers.
The cmd/loader is a preliminary sketch of the load testing tool.
2020-07-31 20:10:43 -04:00
tgruben
d0c2b80021
Merge pull request #631 from molecula/rbf_thurs
rbf: OffsetRange, ImportRoaringBits, CountRange work
2020-07-30 19:30:04 -05:00
Jason Aten
a3d802f8a3 rbf: OffsetRange, ImportRoaringBits, CountRange work
green:
TestFragment_RowsIteration/combinations
TestFragment_RoaringImportTopN

red: (needs Ben's attention)
PILOSA_TXSRC=rbf go test -v -run TestFragment_TopN_IDs  -tags=' shardwidth20'  "-gcflags=all=-d=checkptr=0"

also red: (one for Ben)
TestCursor_FirstNext_Quick/9 is throwing
  panic: cannot find segment containing WAL page: 1
  as we check the error back from checkpoint() in Rollback().
2020-07-30 20:20:38 -04:00
jaten-molecula
2fb76ba919
Merge pull request #626 from molecula/rbf_dump
rbf Dump() and DumpString() debug methods.
2020-07-30 13:57:30 -04:00
Jason Aten
8903d8c117 rbf Dump() and DumpString() debug methods. 2020-07-30 13:50:36 -04:00
jaten-molecula
d2586210a2
Merge pull request #621 from molecula/bluegreen_atg
blueGreenTx roaring vs badger is all tests green (atg)
2020-07-30 12:04:11 -04:00
Jason Aten
72c893a3d1 blueGreenTx roaring vs badger is all tests green (atg).
back to github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200709123515-8e896a7af361  b/c github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200718033852-37ee16d8ad1c had issues with CI on 386 and arm
2020-07-30 11:50:25 -04:00
Cody Soyland
5c5cd1e1fd
Merge pull request #620 from codysoyland/go-mod-tidy
Add CI job to ensure go mod files are tidy
2020-07-29 18:18:37 -05:00
Cody Soyland
55313bd69d Add CI job to ensure go mod files are tidy. 2020-07-29 15:28:58 -05:00
Ben Johnson
55c0785215
Merge pull request #597 from molecula/rbf-tx
Implement pilosa.Tx for RBF
2020-07-29 11:42:20 -06:00
Ben Johnson
64de208170 Implement pilosa.Tx for RBF 2020-07-29 11:25:41 -06:00
jaten-molecula
4cdf62ab89
Merge pull request #615 from molecula/parallelized_open_frag
Parallelize view.OpenFragmentsInTx
2020-07-28 11:18:13 -04:00
Jason E. Aten
71eccd121d fix race in view.openFragmentsInTx 2020-07-28 07:55:28 -04:00
Jason Aten
38eea9b4a7 reparallelize view.go openFragmentsInTx() 2020-07-28 07:55:28 -04:00
jaten-molecula
1a89fc27a1
Merge pull request #605 from molecula/badger_atg
Tx integration milestone
2020-07-27 20:44:12 -04:00
Jason Aten
ac7be132ef Tx integration milestone
a) All tests green under -race for both PILOSA_TXSRC=roaring and PILOSA_TXSRC=badger.

b) Distinct is merged back into mainline pilosa.

Seebs notes on the Distinct work:

merge Distinct plugin back into main source tree, convert to Tx

We drop all references to the Preemptively Deprecated Don't You Dare
Use This extension interface, and move the one and only extension we had
(Distinct) into the main executor.

Also this fixes an arguable bug, which is that Container.AsBitmap()
would panic on a nil parameter, but it should have returned an empty
bitmap, because a nil *Ccontainer is a valid empty container. This
simplifies logic significantly in Distinct.

Fixes #569 #570 #571 #572 #573 #584 #585
2020-07-27 19:29:46 -04:00
Ben Johnson
efc90a6d36
Merge pull request #596 from molecula/rm-rbf-fun-dot
Remove generation of rbf/fun.dot in tests
2020-07-23 10:12:17 -06:00
Ben Johnson
75930ed82f Remove generation of rbf/fun.dot in tests 2020-07-23 09:37:50 -06:00
alanbernstein
7c94828a3c
Merge pull request #589 from alanbernstein/broken-index-translation
Fix broken index key translation in state DEGRADED
2020-07-22 21:22:06 -05:00
Alan Bernstein
5ffc7d7b59 Move checkClusterStatus to test package 2020-07-22 19:54:44 -05:00
Travis
339b76a091 use c.Topology, when available, to determine partitionNodes 2020-07-22 16:41:53 -05:00
Alan Bernstein
a727c74d35 Use nodes from topology to calculate partitionNodes 2020-07-22 16:41:53 -05:00
Alan Bernstein
6c8e2e9450 Add test 2020-07-22 16:41:53 -05:00
Alan Bernstein
fa77a36e83 Improve 'shouldn't ever happen' error messages 2020-07-22 16:36:02 -05:00
Jaden Weiss
fd65384faa
Merge pull request #583 from jaddr2line/bsi-test
Test every possible BSI comparison up to 6 bits
2020-07-21 15:58:31 -04:00
Jaden Weiss
9072b4c290
test every possible BSI comparison up to 6 bits 2020-07-21 13:56:36 -04:00
seebs
f5a228e56d
Merge pull request #579 from seebs/shutdownresize
Handle cluster shutdown during a resize
2020-07-21 12:45:18 -05:00
seebs
aae1d25152
Merge branch 'master' into shutdownresize 2020-07-21 12:27:33 -05:00
Jaden Weiss
adde0fa0bc
Merge pull request #564 from jaddr2line/fix-between-common-bits
Fix BSI range queries with nonzero common upper bits and oversized BSI queries
2020-07-21 13:24:00 -04:00
Jaden Weiss
9fb5f8b349
Merge branch 'master' into fix-between-common-bits 2020-07-21 13:19:15 -04:00
Seebs
99420b564e Handle cluster shutdown during a resize
The new logic to send resize instructions more makes it easier
to hit this, but it's probably always been a theoretically possible
bug to hit: If you are shutting a cluster down, then you stop accepting
connections, which means that if you have an existing resize job, you
can't get responses for it. Which means that the other nodes will
fail to notify you of the success or failure of resize instructions,
so the code waiting on the resize job's status waits forever.

When closing, we bail immediately on that; we don't need to wait for
those notifications. We still have a buffer, and a reasonable confidence
that we'll never write more than one result status, so if one of them
*does* somehow show up and cause the job to have a status,
writing the status won't block.
2020-07-21 12:16:38 -05:00
jaten-molecula
4c0d66703e
Merge pull request #582 from molecula/fix575b
remove premature configuration of Txsrc in test config
2020-07-20 21:04:46 -04:00
Jaden Weiss
e6b4cc2f32
fix oversized rangeEQ 2020-07-20 20:43:50 -04:00
Jaden Weiss
b9b0dd293f
fix rangeBetween when there are nonzero common upper bits and oversized rangeGT 2020-07-20 20:38:32 -04:00
Jason Aten
f5688fa700 remove premature configuration of Txsrc in test config 2020-07-20 20:22:47 -04:00
jaten-molecula
d23ea94ec0
Merge pull request #581 from molecula/fix575
pilosa server --tx compatible with PILOSA_TXSRC. fixes #575
2020-07-20 18:48:40 -04:00
Jason Aten
7fe7ed907f env PILOSA_TXSRC is reinjected into the env if pilosa server --tx overrides it. fixes #575
1. Tests can choose the Tx engine desired by setting the PILOSA_TXSRC
      env variable. For example:

         PILOSA_TXSRC=badger go test -v -run TestImportClearRestart

   2. pilosa server --tx is enabled now.

     Examples:
      pilosa server --tx roaring    # gives the legacy approach.
      pilosa server --tx rbf        # will activate RBF
      pilosa server --tx badger     # will activate BadgerDB
      pilosa server --tx badger_rbf # will run Blue-Green badger to RBF comparisons.

      and so forth. See pilosa server -h or txfactory.go for all valid --tx choices.

   3. Mechanism that makes both tests(1) and pilosa server(2) work at once:
       pilosa/server/server.go injects PILOSA_TXSRC into env to
       communicate with NewIndex in pilosa/index.go.
2020-07-20 17:56:12 -04:00
jaten-molecula
22fd24566a
Merge pull request #580 from molecula/fix568
green TestImportClearRestart on PILOSA_TXSRC=badger. fixes #568
2020-07-20 17:24:29 -04:00
Jason Aten
8a1dabb3ba 60m timeout on race 2020-07-20 17:09:32 -04:00
Jason Aten
f59f8a369e green TestImportClearRestart on PILOSA_TXSRC=badger. fixes #568 2020-07-20 16:32:34 -04:00
jaten-molecula
1c9ef3d321
Merge pull request #565 from molecula/tx_roaring_badger
integration of Tx, RoaringTx and BadgerTx implementations.
2020-07-20 16:01:45 -04:00
Jason Aten
97b530ca78 integration of Tx, RoaringTx and BadgerTx implementations.
- all tests green on RoaringTx
  - RoaringTx on by default
  - blueGreenTx testing framework available for A-vs-B comparison
    of Tx implementations
  - flag -tx added to server command line but not wired to
    change NewIndex() selection yet.
  - 918 green tests, 14 tests red on BadgerTx.

    A full list of the 14 red tests on BadgerTx follows.
    Note that these red tests represent not defects in BadgerDB
    or BadgerTx but rather failures of the pre-existing pilosa infrastructure to yet
    be fully adapted from files to using a transactional storage engine.

    As such these are tests that RBF should not be expected to
    pass yet either.

    Fixing the pilosa infrastructure to allow these tests
    to go green under Badger is the next and highest priority
    order of business, but RBF can get much testing benefit
    from the 918 green tests we do have, and hence we merge
    as much as we have today.

    The 14 red tests when NewIndex() is set to use
    BadgerTx are as follows. Note in particular
    that pilosa cluster resizing is not working yet under a
    transactional store.

     TestCluster_ResizeStates/Multiple_nodes,_with_data
     TestImportClearRestart/0MaxOpN10000
     TestImportClearRestart/1MaxOpN10000
     TestImportClearRestart/2MaxOpN10000
     TestImportClearRestart/3MaxOpN10000
     TestExecutor_Execute_Existence/Row
     TestExecutor_ForeignIndex
     TestExecutor_Execute_CountDistinct/Distinct
     TestExecutor_Execute_CountDistinct/Count(Distinct)
     TestExecutor_Execute_CountDistinct/GroupBy(Distinct)
     TestExecutor_BareDistinct
     TestExecutor_Execute_TopNDistinct/TopN
     TestHolderSyncer_IntField/BasicSync
     TestHolderSyncer_IntField/MultiShard
2020-07-20 15:50:08 -04:00
seebs
ab6a3aff10
Merge pull request #458 from seebs/eaddrinuse
Fix very-sporadic EADDRINUSE failures in CI testing (and related cluster test issues)
2020-07-20 10:58:48 -05:00
Seebs
364b533ead various cluster test fixups/cleanups
Some cluster tests failed sporadically. In order to fix them, I
introduced some debugging-related functionality, which revealed
several new bugs that were actually existing bugs we just happened
not to hit in testing. This combines various fixes.

We start with "make the nodes used in testing have distinct names
based on the test case name", which lets us discover that we are
leaking clusters, which continue to sit around talking with each
other. That in turn causes significantly higher load on access to
ephemeral ports, which causes sporadic failures when we shut a
node down and try to restart it, but something else has gotten assigned
its ephemeral port number since then.

Part of the fix is to try to rebind on port 0 if an attempt to
bind to a specified port over 32k fails. This is a guess; the
actual ephemeral port range could be 16k+, 32k+, or 48k+, or just
about anything else really, but it seems reasonable in
practice.

There were bugs in the oft-repeated loops to await the cluster
achieving a given state, and it could hang forever if it didn't,
so we add a timeout and a standard function on the test.Cluster
type to handle that. Note that the timeout seems irrelevant; in
every case I've tried, a timeout of 0 is fine because the node
start doesn't complete until the cluster state has changed.

Add a method to test.Command to run a query, expecting a specific
result. Also clean up some of the formatting and generation of
queries, and allow parameterized (badly) queries. This lets us fix
a subtle bug, which is that test cases were depending on assumptions
about shardwidths. Also improve the diagnostic output from some of
these functions so test failures are more comprehensible.

But actually that dependency on shardwidths was ALSO revealing a
genuine underlying bug, which is that a node resize did not correctly
propagate the schema to a new node if there was no data present
on shards that node would own. We now also have a test case that
hits that (or would, if we hadn't fixed it).

Add comments explaining the server options parameters for MustNewCluster
and MustRunCluster.

Also, we implement the ReadFrom and WriteTo behaviors for
InMemTranslateStore, without which some of the cluster resize tests
fail. Props to the comment for specifically stating that they wouldn't
work if that happened, which probably saved me several hours of
debugging. The implementations may not be robust, but
InMemTranslateStore is intended to be used only in lightweight
and transient testing.
2020-07-20 10:45:59 -05:00
Seebs
ef8b054367 move Cluster type and methods into existing almost-empty cluster.go 2020-07-20 10:45:47 -05:00
tgruben
1067d29784
Merge pull request #547 from tgruben/refactor-putleaf
refactor putleaf
2020-07-17 13:39:35 -05:00
Todd Gruben
cd4bd016f9 skipping a test for ci issue 2020-07-17 09:30:07 -05:00
Todd Gruben
848359a36b skipped test for race wip 2020-07-17 09:15:20 -05:00
Todd Gruben
e61f0f6b1f missing liscense 2020-07-17 09:09:42 -05:00
tgruben
88bf29ea40
Merge branch 'master' into refactor-putleaf 2020-07-17 09:06:31 -05:00
Todd Gruben
9bbceb931a missing license 2020-07-17 09:05:53 -05:00
Todd Gruben
7c5c693fcb linter fix 2020-07-17 09:03:32 -05:00
Todd Gruben
59d2d89a5c removed leafArg and added conatinertypebitmapptr; lint fixes 2020-07-17 02:16:35 -05:00
Jaden Weiss
3f45a90582
Merge pull request #549 from jaddr2line/microseconds
Add microseconds to log
2020-07-16 17:13:10 -04:00
Jaden Weiss
de061ff21d
Merge branch 'master' into microseconds 2020-07-16 17:01:50 -04:00
Todd Gruben
bbd83e4618 . 2020-07-16 08:31:09 -05:00
Kuba Podgórski
2ee5e3d8e5
Merge pull request #538 from kuba--/translation-coordinator
Translation coordinator
2020-07-15 22:53:18 +02:00
Kuba Podgórski
ce628c96cd
Merge branch 'master' into translation-coordinator 2020-07-15 22:45:43 +02:00
Kuba Podgórski
1d6a4dea88
Merge pull request #554 from kuba--/i0-i1
Remove test leftovers
2020-07-15 14:06:23 +02:00
Kuba Podgórski
559e71f62a Remove test leftovers (holder's path). 2020-07-15 13:50:59 +02:00
Jaden Weiss
5579d632c7
Merge pull request #539 from jaddr2line/remove-arm64-binary
remove an arm64 pilosa binary that was committed for some reason
2020-07-14 20:08:23 -04:00
Kuba Podgórski
1edd773e90
Merge branch 'master' into remove-arm64-binary 2020-07-15 01:42:26 +02:00
Jaden Weiss
c99d35a793
Merge pull request #552 from jaddr2line/queries-docs
Add /queries endpoint to API reference
2020-07-14 18:26:27 -04:00
Jaden Weiss
b442ff8336
add /queries endpoint to API reference 2020-07-14 15:58:59 -04:00
Jaden Weiss
9036a16b08
add microseconds to log 2020-07-14 11:44:55 -04:00
Todd Gruben
e68f0a0d8f missing license 2020-07-14 09:00:09 -05:00
Todd Gruben
b61bdbd7a0 fix linter errors 2020-07-14 08:54:30 -05:00
Todd Gruben
374a4ec9ce fixed missing refactor test;refactor GetBitmap 2020-07-14 07:57:02 -05:00
Todd Gruben
b8fe08c765 simplify Walker interface 2020-07-13 20:34:33 -05:00
Todd Gruben
d6986b78a5 . 2020-07-13 20:08:22 -05:00
Todd Gruben
b2b614a686 refactor cursor.GetBitmap->tx.GetBitmap;rename to WalkRootRecordPages;err check 2020-07-13 19:32:26 -05:00
Todd Gruben
b11b43af43 refactor putleaf 2020-07-13 10:48:25 -05:00
Travis Turner
3c619fa2ef
Merge pull request #543 from travisturner/foreign-index-todos
Get ForeignIndex keys in GroupBy
2020-07-11 19:45:31 -05:00
Travis Turner
9f80619f19
Merge branch 'master' into foreign-index-todos 2020-07-11 18:24:55 -05:00
Kuba Podgórski
92ab76b621
Merge pull request #399 from molecula/alisharawal-patch-1
Update README.md
2020-07-11 21:28:14 +02:00
Kuba Podgórski
51ba2492e9
Merge branch 'master' into translation-coordinator 2020-07-11 19:22:48 +02:00
Kuba Podgórski
51891040d0
Merge branch 'master' into alisharawal-patch-1 2020-07-11 19:17:30 +02:00
Travis
a9dc8b8add
translate GroupBy previous value from foreign index 2020-07-11 10:18:45 -05:00
Travis
8f6b876af0
get ForeignIndex keys in GroupBy 2020-07-10 22:48:35 -05:00
alanbernstein
07d3cfe23b
Merge pull request #542 from alanbernstein/validate-transaction-id
Restrict allowed characters in transaction IDs
2020-07-10 20:18:42 -05:00
Kuba Podgórski
0fc7b89b48
Merge branch 'master' into remove-arm64-binary 2020-07-11 01:59:35 +02:00
Kuba Podgórski
010ab5ef8b Extend translate coordinator test 2020-07-11 01:51:03 +02:00
Alan Bernstein
65febc37fd Allow '' in ID regex 2020-07-10 18:07:17 -05:00
Alan Bernstein
7c37ececfd Restrict allowed characters in transaction IDs 2020-07-10 17:58:47 -05:00
Jaden Weiss
a947bc8ad9
Merge pull request #540 from jaddr2line/fix-inspect-query-validate
Fix incorrect validation of query specification in Inspect
2020-07-10 15:56:07 -04:00
Jaden Weiss
2f8d8345c1
fix incorrect validation of query specification in Inspect 2020-07-10 14:35:30 -04:00
Jaden Weiss
8940402e76
remove an arm64 pilosa binary that was committed for some reason 2020-07-10 13:28:27 -04:00
Travis Turner
c7ccd62b3b
Merge pull request #537 from travisturner/grpc-port-0
Replace grpc port code that I removed for some reason
2020-07-10 11:06:40 -05:00
Travis
85bd306eb5
replace grpc port code that i removed for some reason 2020-07-10 10:57:20 -05:00
Jaden Weiss
bb9b3d4e6f
Merge pull request #527 from jaddr2line/like
Add `Rows(like=...)` and `UnionRows` queries
2020-07-09 19:10:29 -04:00
Jaden Weiss
239aacc160
Merge branch 'master' into like 2020-07-09 19:04:03 -04:00
Jaden Weiss
62ce26e7b8
Merge pull request #534 from jaddr2line/inspect-query-v2
Add support for inspecting with a query
2020-07-09 14:09:47 -04:00
Jaden Weiss
f4e9e1688f
add support for inspecting with a query 2020-07-09 13:29:15 -04:00
Travis Turner
85d1fa30dc
Merge pull request #530 from travisturner/advertise-grpc
add --advertise-grpc configuration option
2020-07-09 11:38:18 -05:00
Travis
944a6dca78
add --advertise-grpc configuration option 2020-07-09 11:17:12 -05:00
Ben Johnson
3c021fc2e3
Merge pull request #526 from molecula/rbf
Roaring Bitmap Format
2020-07-08 13:39:37 -06:00
Ben Johnson
de51b538f3 rbf: roaring bitmap format
Co-authored-by: Todd Gruben <todd@pilosa.com>
2020-07-08 13:27:18 -06:00
Jaden Weiss
4bacab6524
update query language docs to include like and UnionRows 2020-07-08 13:08:11 -04:00
Jaden Weiss
c9edccb267
add executor tests and license headers for like & UnionRows 2020-07-08 12:55:18 -04:00
Jaden Weiss
7a16ffff68
add UnionRows query 2020-07-08 12:55:18 -04:00
Jaden Weiss
227881cb67
simplify suffix matching 2020-07-08 12:55:17 -04:00
Jaden Weiss
0611ef3418
initial implementation of Rows like 2020-07-08 12:55:17 -04:00
Jaden Weiss
ed8e5a933e
optimize & document & test like matcher
optimize suffix matching
add some descriptive comments to the like matcher
test all paths in the like tokenizer and matcher
2020-07-08 12:55:17 -04:00
Jaden Weiss
9eb8fcb37f
initial impl of like 2020-07-08 12:55:17 -04:00
alanbernstein
7f1b1f63ef
Merge pull request #506 from alanbernstein/docs-updates
Docs updates
2020-07-07 15:27:07 -05:00
alanbernstein
0aae064310
Merge branch 'master' into docs-updates 2020-07-07 15:17:42 -05:00
Alan Bernstein
94038f4446 Update wording 2020-07-07 03:48:37 -05:00
Ben Johnson
d53d8ef010
Merge pull request #508 from molecula/tx
Tx Interface
2020-07-02 17:20:23 -06:00
Ben Johnson
bf55bbc717 Tx Interface
This commit adds a transaction interface which will be used in the
future to add support to RBF (Roaring B-tree Format).
2020-07-02 10:43:15 -06:00
Kuba Podgórski
549c98dc64
Merge pull request #447 from kuba--/union-run-run
Add unionRunRunInPlace
2020-07-02 11:05:27 +02:00
Kuba Podgórski
751383ecb1
Merge branch 'master' into union-run-run 2020-07-02 10:52:59 +02:00
Jaden Weiss
a52c5d803d
Merge pull request #510 from jaddr2line/roaring-cleanup-3
Roaring cleanup
2020-07-01 17:21:14 -04:00
Jaden Weiss
6d692487ed
Merge branch 'master' into roaring-cleanup-3 2020-07-01 17:15:10 -04:00
Kuba Podgórski
ec73bf5906
Merge branch 'master' into union-run-run 2020-07-01 22:25:06 +02:00
Kuba Podgórski
e777a28283
Merge pull request #513 from kuba--/todo-501
Address the overflow issue with values outside the int64 range
2020-07-01 21:09:09 +02:00
Kuba Podgórski
4bed1df101 Address the overflow issue with values outside the int64 range 2020-07-01 20:40:47 +02:00
Kuba Podgórski
d6caf34c02
Merge pull request #509 from kuba--/todo-503
Add test for Rows on bool
2020-07-01 16:32:24 +02:00
Kuba Podgórski
f0abb5e8b4
Merge branch 'master' into todo-503 2020-07-01 16:23:38 +02:00
Kuba Podgórski
e52b1c04fc
Merge pull request #512 from kuba--/todo-504
FieldValue - check if column arg exists
2020-07-01 16:06:16 +02:00
Kuba Podgórski
5bbb3e2065 FieldValue - check if column arg exists 2020-07-01 11:36:42 +02:00
Kuba Podgórski
58964947d4
Update executor_internal_test.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-07-01 10:17:30 +02:00
Kuba Podgórski
f921c5ded0 Add test for Rows on bool 2020-07-01 01:30:36 +02:00
Jaden Weiss
3e0ce32d00
roaring cleanup 2020-06-30 16:38:16 -04:00
Alan Bernstein
3841419907 Use more believable words 2020-06-30 12:23:36 -05:00
Alan Bernstein
31ae30f703 Replace smart quotes 2020-06-30 11:26:25 -05:00
Alan Bernstein
5a6db1cc2b Document topn heuristic behavior 2020-06-30 11:26:16 -05:00
Jaden Weiss
ad2390444a
Merge pull request #500 from molecula/seebs-big-inspect-pr
Improve inspect output, switch roaring over to using new unmarshal, handle inspecting whole holders
2020-06-29 15:31:01 -04:00
Jaden Weiss
31014d11e5
remove unnecesary slice operation when processing holder 2020-06-29 15:22:27 -04:00
Seebs
4d494f6699
shared/generic functionality for iterating holders
This is sort of large, but it's annoyingly difficult to
separate out.

The basic idea is to allow us to have a single holder-iterating
block of code, which is associated with the holder, that can be used
for various things, like the snapshot queue background scan, or
for inspect operations.

We invent the concept of a HolderFilter, which is a thing that
can decide what things in a holder it cares about, and a HolderOperator,
which can also process those things selectively.

In the process, we fix up a couple of subtle bugs in the
inspect logic; specifically, the assumption that the mapped flag could
tell you whether a container was modified by the ops log doesn't
work with mmap, so we have a shiny new flag which is used to track
that, internal to the roaring/container code.

All of this leads to the actual *point* of this exercise, which is
making it easier to create an /inspect endpoint which produces almost
the same data we'd have gotten from `pilosa inspect` on a data directory;
the distinction is that it doesn't try to identify the distinction
between data from disk and data from operations since the file was
loaded. Possibly it should, but it doesn't yet.

The snapshot queue is now implemented using the HolderOperator
design, which requires some subtle changes to how it works, but
overall makes it easier to follow the snapshot queue logic,
and also shares that logic with the way Inspect works.

The holder's snapshot queue is now provided by the server, in
a default environment.

The queueless snapshot queue no longer triggers snapshots on
enqueue -- it turns out that breaks badly, because a key
point about enqueueing a snapshot is that it's safe to do it
*during* a transaction on that fragment, and triggering a
snapshot during a transaction actually causes horrible errors
as the ops log ends up being the old file, which we close.
Related to this, we also need to prevent closed fragments from
trying to snapshot, so we track fragment openness when opening
or closing, and bail on trying to snapshot a fragment which is closed.

We also stop using the queueless snapshot queue during tests,
because that's a horrible idea.

We copy a little bit of the partition logic from the cluster code so
we don't have to expose it all, this lets us check whether the node
we're looking at is the one which should be primary for a given shard,
and if not, identify which node would be. This works only when
pointed at a data directory, for now.

The test cases for the holder have to be internal, because pilosa
doesn't export view/fragment, just Index/Field. This means that the
holder test cases can't just use the test/* package, so they duplicate
some of its logic, approximately.
2020-06-29 15:18:47 -04:00
Seebs
2826ecc0b7
track retries correctly in truncation case 2020-06-29 15:13:51 -04:00
Seebs
176d49e4b5
use syswrap to close file after opening it with syswrap 2020-06-29 15:13:50 -04:00
Seebs
3e7f0b32e9
drop old Call data while processing a list of calls
We don't need the Calls anymore, and especially Precomputed calls
(like Distinct) could be a significant memory load that's increased
as we process additional calls, so we drop the Precomputed references.
We can't drop the calls entirely -- translation can require lookups of
call arguments.
2020-06-29 15:13:50 -04:00
Seebs
7e7051d387
don't try to truncate files when invoked read-only 2020-06-29 15:13:50 -04:00
Seebs
ceaf5c15d1
thread the holder through things, and improve snapshot queue logic
This is logically two separate things, but the individual changes
are thoroughly intertwined in the code.

The first change is a logical change to the design of the snapshot
queue, which is that it now adjusts the maxOpN the background scan
targets, allowing it to lower that value over time when things are
quiet. We do this because it turns out that on large data sets,
this can make a factor-of-four difference in memory usage!

So, in general, on a quiet system, each pass through the holder
aims for about 1/4 of the existing fragments to get snapshotted.
When there's more load, we adjust those values up.

We also make the snapshot queue a bit less chatty, to make testing
less annoying -- we only print stats if the queue enqueues at least
two snapshots, or skips any.

The second change is threading the holder through things. We've
always threaded the logger through, and then added the snapshot
queue, and some of the Inspect-related work led to wanting to
have a way to thread options through, so what if we just threaded
the holder itself through, and removed the direct copying around
of the logger, snapshot queue, and so on. Similarly, everything
can now use holder.PartitionN instead of having to get its own
copy of PartitionN handed out to each index.

This does imply ensuring that test cases always get a reasonable
default holder.

This is a precursor to adding additional information to the holder,
such as whether it's in a special read-only mode, which would imply
not modifying on-disk files. This is already semi-supported for
the specific case of the background snapshot queue and cache flushing,
which are attached to the (created in a previous commit) new
holder Activate method, instead of being automatic on holder Open.

The change to a snapshot queue can also cause races in tests, because
the fragment.Clean method's "sanity check" accesses a fragment without
a lock. Fix that. Since there's a couple of t.Fatalf(), but we need
to release the lock before closing, we use an anonymous function
with a defer to handle that. Whee!
2020-06-29 15:13:50 -04:00
Seebs
121717594b
improve inspect output, switch roaring over to using new unmarshal
At some point the code changeover to use roaring iterators for
unmarshal got dropped, but the old unmarshal code is way harder to
make work for inspect, so this change is back.

This exports some of the names from the things returned by Info,
but also adds a roaring function to use the unmarshalling logic on
arbitrary data, allowing us to get more insight into a file -- in
particular, letting us distinguish between the bitmaps specified by
the roaring data and the bitmaps resulting from applying the ops log.
2020-06-29 15:13:47 -04:00
Jaden Weiss
c1612851af
Merge pull request #498 from jaddr2line/transaction-test-timeout
TestTransactionManager: raise transaction timeouts to avoid sporadic failures
2020-06-29 14:42:21 -04:00
Jaden Weiss
0d05e413d3
TestTransactionManager: raise transaction timeouts to avoid sporadic failures 2020-06-29 13:44:20 -04:00
Jaden Weiss
a175858375
Merge pull request #496 from jaddr2line/molecula-rebrand
Rebrand pilosa binaries
2020-06-26 17:51:21 -04:00
Jaden Weiss
fedb1f7dbd
set version to match Molecula convention 2020-06-26 17:41:19 -04:00
Jaden Weiss
4a4252bb28
Merge pull request #1 from codysoyland/enterprise-removal
Remove a few more enterprise references
2020-06-26 17:24:02 -04:00
Cody Soyland
4f22c388b3 Remove a few more enterprise references 2020-06-26 15:57:21 -05:00
Jaden Weiss
cd317d7e91
tweak VERSION_ID 2020-06-26 16:49:06 -04:00
Jaden Weiss
aa1995073f
rebrand pilosa binaries
This change rebrands the Pilosa binaries from "Pilosa Enterprise" to "Molecula Pilosa" and simplifies the version info string.
2020-06-26 16:49:05 -04:00
Kuba Podgórski
d99971a6c2
Merge branch 'master' into union-run-run 2020-06-26 22:32:07 +02:00
Kuba Podgórski
8b33a073b4
Merge pull request #495 from kuba--/int-eq
Support '=' condition for int/decimal fields
2020-06-26 22:30:03 +02:00
Kuba Podgórski
4351464f84
Merge branch 'master' into int-eq 2020-06-26 21:26:44 +02:00
Jaden Weiss
a78b1cfe19
Merge pull request #446 from jaddr2line/fastrank
Remove allocations from ranked cache when possible
2020-06-26 12:46:58 -04:00
Kuba Podgórski
3782c3ac14 Support '=' condition for int/decimal fields 2020-06-26 18:14:59 +02:00
Jaden Weiss
94b55f8556
remove allocations from ranked cache when possible 2020-06-26 12:12:51 -04:00
Jaden Weiss
079bee5711
Merge pull request #489 from jaddr2line/field-cleanup
Remove unused field code
2020-06-26 11:37:15 -04:00
Jaden Weiss
5523587435
pilosa: remove unused field code 2020-06-26 10:14:56 -04:00
Kuba Podgórski
76324f1498
Merge branch 'master' into union-run-run 2020-06-26 01:28:25 +02:00
Jaden Weiss
0a030e9a77
Merge pull request #482 from jaddr2line/rm-invalid-unsafe
Remove invalid uses of unsafe from roaring containers
2020-06-25 15:02:33 -04:00
Jaden Weiss
934048bb02
roaring: remove invalid uses of unsafe 2020-06-25 11:48:21 -04:00
Kuba Podgórski
47481432ef
Merge pull request #468 from kuba--/fix-DEGRADED
Lets the remote node to proceed
2020-06-25 17:05:30 +02:00
Kuba Podgórski
80cfb5c182
Merge branch 'master' into fix-DEGRADED 2020-06-25 16:41:41 +02:00
Kuba Podgórski
0bdb420b4c
Merge pull request #475 from kuba--/fix-iface-conv
Make a safe cast
2020-06-25 15:36:53 +02:00
Kuba Podgórski
ed86f6ea5d Make a safe cast 2020-06-25 14:44:14 +02:00
Cody Soyland
bc9d13206f
Merge pull request #490 from codysoyland/ci-fixes
Fix/refactor CircleCI config
2020-06-24 13:52:45 -05:00
Cody Soyland
2024228153 Fix/refactor CircleCI config
- Fix incorrect usage of workspaces (vendor dir in current directory no
  longer primary cache of go modules)
- Refactor checkout, github-auth, and mod cache into a reusable command
- Fix issue with dockerhub upload and github authentication
2020-06-24 13:45:17 -05:00
Kuba Podgórski
413ce4f1ab
Merge branch 'master' into fix-DEGRADED 2020-06-24 19:56:24 +02:00
Jaden Weiss
2925101b09
Merge pull request #487 from jaddr2line/cluster-message-error
Differentiate between cluster message request errors and cluster message processing errors
2020-06-24 09:44:03 -04:00
Jaden Weiss
b5b60b8912
http: differentiate between cluster message request errors and cluster message processing errors 2020-06-24 09:23:08 -04:00
Kuba Podgórski
905cda7f08 Add benchmarks 2020-06-23 22:18:13 +02:00
Kuba Podgórski
443f2d8f7c The third attempt to implement unionRunRunInPlace 2020-06-23 22:18:13 +02:00
Kuba Podgórski
eddbb7d0b0 Optimize run intervals by combnining neighbours 2020-06-23 22:18:13 +02:00
Kuba Podgórski
2b0cd2f234 Add unionRunRunInPlace 2020-06-23 22:18:13 +02:00
Jaden Weiss
89ac3f4737
Merge pull request #486 from jaddr2line/handlerfixes
Fix incorrect error handling in HTTP handler and output raw error text when JSON is not selected
2020-06-23 12:57:55 -04:00
Jaden Weiss
66aef92cfa
http: fix incorrect error handling and output raw error text when JSON is not selected 2020-06-23 12:26:37 -04:00
Cody Soyland
16ebdf290d
Merge pull request #479 from codysoyland/ci-dockerhub-fix
Fix and simplify CI DockerHub integration
2020-06-23 09:13:41 -05:00
Cody Soyland
7cb9548097 Fix and simplify CI DockerHub integration 2020-06-19 11:41:54 -05:00
Jaden Weiss
5dc02a3998
Merge pull request #474 from jaddr2line/timeclr
Fix Clear() returning `false` when it should return `true`
2020-06-19 09:03:42 -04:00
Jaden Weiss
a270bff67b
fix Clear() returning false when clearing a bit with no time views 2020-06-19 08:51:08 -04:00
Kuba Podgórski
739935c3f6
Merge branch 'master' into fix-DEGRADED 2020-06-18 16:13:58 +02:00
tgruben
21888703e5
Merge pull request #469 from tgruben/splat-init
Functionalize  fillerBitmap initialization
2020-06-17 09:39:16 -05:00
tgruben
3103da2c19
Update roaring/container_stash.go
Co-authored-by: Jaden Weiss <jaden@jadendw.dev>
2020-06-17 08:51:25 -05:00
Todd Gruben
f47888989a shorten fillerBitmap initialization 2020-06-17 07:12:24 -05:00
Kuba Podgórski
87306d3145 Lets the remote node to proceed, instead of waiting in DOWN state because cluster is in STARTING state. 2020-06-17 11:37:30 +02:00
Jaden Weiss
7f4142497e
Merge pull request #467 from jaddr2line/splat
Optimize `splatRun`
2020-06-16 13:50:27 -04:00
Jaden Weiss
8fc7861148
roaring: optimize splat 2020-06-16 13:04:50 -04:00
Travis Turner
cf24ee161f
Merge pull request #465 from travisturner/document-shift
Add comments warning that Shift() is unsupported
2020-06-15 17:53:38 -05:00
Travis
c5786e1d78
Add comments warning that Shift() is unsupported 2020-06-15 17:16:00 -05:00
alisharawal
4a68b46597
Merge branch 'master' into alisharawal-patch-1 2020-06-15 11:15:14 -05:00
Jaden Weiss
d9baea83f4
Merge pull request #454 from jaddr2line/groupbyoffset
Apply base in GroupBy on BSI
2020-06-11 17:24:39 -04:00
Jaden Weiss
837d0a1465
Merge branch 'master' into groupbyoffset 2020-06-11 12:20:35 -04:00
Jaden Weiss
32e47642ae
address review of "Apply base in GroupBy on BSI" 2020-06-10 17:49:00 -04:00
tgruben
8bc303793c
Merge pull request #453 from tgruben/includes-perf
Optimized performance of row.Includes
2020-06-10 15:50:50 -05:00
Jaden Weiss
535257af75
apply base in GroupBy 2020-06-10 16:16:53 -04:00
Todd Gruben
416f332070 Optimize row.Includes 2020-06-10 13:12:38 -05:00
Jaden Weiss
ec9474114a
Merge pull request #449 from jaddr2line/fixbsioffbyone
Fix BSI comparison match-all-but-one operation
2020-06-10 10:41:35 -04:00
Jaden Weiss
8887927dbd
add regression test for BSI match-all-but-one operations 2020-06-10 10:09:33 -04:00
Jaden Weiss
d478dd9d94
fix BSI comparison match-all-but-one operation 2020-06-10 09:23:39 -04:00
Kuba Podgórski
058ed747c7
Merge pull request #437 from kuba--/err-check
Return error instead of panicking on Store(Distinct())
2020-06-09 14:53:23 +02:00
Kuba Podgórski
9c3b080bf0 Check result before return 2020-06-09 11:39:16 +02:00
Cody Soyland
a519907822
Merge pull request #440 from codysoyland/ci-size
Use xlarge executor in CircleCI
2020-06-08 15:24:31 -05:00
Cody Soyland
8352f5d273 Add configurable resource class, enable only for test-race. 2020-06-08 15:20:31 -05:00
Cody Soyland
ecbb5b2a0d Use xlarge executor in CircleCI 2020-06-08 15:20:31 -05:00
Jaden Weiss
12e6534244
Merge pull request #426 from jaddr2line/simplebsi
Simplify BSI comparisons
2020-06-08 16:14:41 -04:00
Jaden Weiss
ee8036d376
Merge branch 'master' into simplebsi 2020-06-08 16:07:29 -04:00
Jaden Weiss
120cc02536
process BSI ops more efficiently 2020-06-08 14:52:19 -04:00
Jaden Weiss
721a968d63
Merge pull request #438 from jaddr2line/cpumhz
fix CPU speed on non-Intel platforms
2020-06-08 13:34:27 -04:00
Jaden Weiss
a4e53b4bc1
Merge branch 'master' into cpumhz 2020-06-08 13:26:49 -04:00
seebs
c0c027ef67
Merge pull request #429 from seebs/racetime
Improve time requirements for tests with race detector on
2020-06-08 12:25:07 -05:00
Seebs
44569fa210 Reduce iterations in TestFragment_RowsIteration
We don't really learn more from trying every multiple of 10,000 than we do
from trying maybe 32 values, and it's worse at larger shard widths.
2020-06-08 12:10:40 -05:00
Seebs
52aa3e2e23 Improve container/bitmap comparison logic for testing
We have a "deadcode" bitmapsEqual which is actually used in testing but
probably shouldn't be, and we don't have a good container equality test.

Problem is, equality tests are sort of slow in the things-are-equal case,
which is the most common case, so we've got some moderately-specialized
code here; specifically, special comparison code that takes advantage
of knowing that if two containers have the same number of bits, you only
have to check whether all the bits from one are present in the other,
because that can't be true for differing containers with the same number
of bits. This reduces the runtime for the ContainerCombinations case
from about 24 seconds to a bit under 2 on my laptop, or from around
10 minutes to about 37 seconds with the race detector on.

Also simplify the InPlaceWrapper functions not to invoke bitmaps, because
it's not really necessary.
2020-06-08 12:10:40 -05:00
Seebs
3f0c9925f4 Don't test quite so many values for BtreeSeek and BtreeDelete
BtreeSeek is O(N^2) on its N, and there's not a ton of extra utility
to testing a larger range of values, so we reduce N by a bit, cutting
runtime from ~10s to <1s on my laptop. Also reduce the scale of the
BtreeDelete1/BtreeDelete2 tests a bit because, again, lots of runtime
for little marginal information.
2020-06-08 12:10:40 -05:00
Seebs
e223c79ace Don't use a whole shard of values for Execute_All test.
This is pretty expensive even for default shard width, and very expensive
for ShardWidth = 1<<22, and we don't really get much extra benefit from
having a million values instead of a hundred or so.
2020-06-08 12:10:40 -05:00
Seebs
1484674a1c Add and use bitmap-to-slice-or-set comparison functions
The generation of slices from things, and use of reflect.DeepEqual to compare
the slices, is a lot more expensive than it needs to be. Omitting it removes most
of the runtime of the marshal tests.
2020-06-08 12:10:40 -05:00
Seebs
1952a43ed4 Write fewer bits to test the rowcache behavior
The failure mode in question was pretty predictable and tied to number of
snapshots, not to number of bits written, so we can probably use a lot fewer
bits and still get good results, but this is really slow under -race testing.
2020-06-08 12:10:40 -05:00
Seebs
1460756b3f Provide option for adjusting node timeouts, set it for tests.
There's no reason to have 10-20 seconds of delays for testing this,
because in testing, we're running things on the local machine and don't
need to worry about significant network lag. Make retry count and delay
settable options, and set them lower. Moves the Replica2 test in
server/server_test.go from ~21s to ~2s.
2020-06-08 12:10:40 -05:00
Seebs
55ff03a2d6 Lower scale of some random-value tests
The random-value tests can be pathological, and in particular, the
test of arbitrarily-spaced values is in effect O(N^2), and with race
testing on, that test *alone* can take ten minutes to run, but
it's not really all that exciting. We just reduce a bunch of values
and/or test fewer things for these, which doesn't significantly alter
coverage, but reduces test runtime on my laptop with `-race` from
21 minutes to a bit under 5.
2020-06-08 12:10:40 -05:00
Jaden Weiss
7695e63bc5
fix CPU speed on non-Intel platforms 2020-06-08 11:40:53 -04:00
Jaden Weiss
0a17b3713c
Merge pull request #428 from jaddr2line/cleanshutdown
Cleanly shut down the executor
2020-06-05 18:32:57 -04:00
Jaden Weiss
b0a0524ffe
cleanly shut down the executor 2020-06-05 15:25:35 -04:00
Jaden Weiss
0ce5d92407
simplify BSI comparisons 2020-06-05 14:13:29 -04:00
seebs
33728e65d9
Merge pull request #408 from seebs/execontext
thread contexts better through executor
2020-06-04 15:18:12 -05:00
seebs
610d72dbfc
Merge branch 'master' into execontext 2020-06-04 14:57:16 -05:00
Jaden Weiss
0095810e4d
Merge pull request #419 from jaddr2line/trackqueries
track active queries
2020-06-04 14:58:22 -04:00
Jaden Weiss
06517075bf
add unit test to active query tracker 2020-06-04 14:05:06 -04:00
Jaden Weiss
1099a57945
fix pretty printing of active queries list to handle special characters and multiline queries 2020-06-04 14:04:46 -04:00
Jaden Weiss
023efcaba6
track active queries 2020-06-04 10:50:15 -04:00
Seebs
439c710ca9 thread contexts better through executor
When a mapper hits an error, we want it to immediately tell the
other things in that same mapper that they can stop now. But we
don't want to propagate that all the way back up; if a specific
node has a failure executing a query, we will in some cases want
to send a new query to other backup nodes, so the overall
context isn't cancelled yet.

In general, mapFn and reduceFn have been closures that inherit
a context from the function defining them -- but we don't want
that! We want them to be stopped if their specific mapper gets
cancelled, too, because otherwise they can consume a lot of
resources long after the mapper has stopped being interested
in them.  So now those are parameters passed into them,
and mapperLocal puts *those* contexts in the jobs shoved into
the job queue, and the workers pass the context in to the
mapFn/reduceFn.

We also check responses from reduceFn now; both mapReduce
and mapperLocal check for a possible error, and return that,
and reduce functions doing anything nontrivial check their
context.

We also add a few more explicit checks for context cancellation
in various places, especially in the GroupByIterator which is
what bit us that one time. The explicit check against ctx.Err
is officially safe as of Go 1.9 or so. (It was previously
unspecified, but on further study, the Go team concluded that
no actual implementation did anything else, and existing code
was already depending on that.) This also affects the rows
function, because that could potentially take quite a while to
run for a large fragment.
2020-06-03 16:09:01 -05:00
seebs
33a90fd328
Merge pull request #297 from seebs/nofreeze
Don't automatically freeze the results of RowSegment ops
2020-06-03 14:54:12 -05:00
Seebs
6abe7dc12f Don't automatically freeze the results of RowSegment ops
I think when this code was written, I thought "freeze" would be
really cheap. It's not actually that cheap. As a result, freezing
things preemptively when it may be that nothing ever tries to write
to them anyway is possibly disadvantageous, to the tune of being
roughly 20% of a sample profile we were shown. Instead, we don't
mark the components "writable", so if anything wants to write to
them, it'll end up freezing itself new copies of their bitmaps
later. But in practice that probably doesn't happen.
2020-06-03 13:21:41 -05:00
Kuba Podgórski
0bba9c81e8
Merge pull request #417 from kuba--/rev-mtx
Change order of cluster/index locks
2020-06-03 15:37:20 +02:00
Kuba Podgórski
0320228b99 Change order of cluster/index locks 2020-06-03 15:09:56 +02:00
Kuba Podgórski
a8e6846e78
Merge pull request #401 from kuba--/etag
Add (in memory) CreatedAt to index and fields
2020-06-03 15:09:22 +02:00
Kuba Podgórski
bb048da241
Update docs/api-reference.md
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2020-06-03 14:47:51 +02:00
Kuba Podgórski
6a892102e4 Update api-reference.md 2020-06-03 13:26:16 +02:00
Kuba Podgórski
d8a417f657 Move applyCreatedAt from mergeClusterStatus directly to ClusterStatus message, to avoid deadlocks 2020-06-03 13:26:16 +02:00
Kuba Podgórski
0c98c887ac Pass Schema in ClusterStatus message 2020-06-03 13:26:16 +02:00
Kuba Podgórski
ba7f039dd1 Rename etag to createdAt 2020-06-03 13:26:16 +02:00
Kuba Podgórski
3d270f45d2 Add (in memory) ETag to index and fields 2020-06-03 13:26:16 +02:00
tgruben
43195ae2dd
Merge pull request #416 from tgruben/fix-grpc-address
add address for listening
2020-06-02 16:25:53 -05:00
Todd Gruben
fdaae31c2c add address for listening 2020-06-02 15:39:28 -05:00
Matthew Jaffee
31c5e7363d
Merge pull request #412 from jaffee/escape-query-strings-411
modify PQL parser to handle escapes in string values
2020-05-29 08:51:54 -05:00
Matt Jaffee
1c1204fc77
modify PQL parser to handle escapes in string values
This modifies the parser to properly "unquote" incoming strings. So if
a string comes in double or single quoted, we approximately follow Go
rules for removing the quotes and processing escape sequences.

The differences from Go are:
1. we only support backslash, quote, tab and newline escape
sequenences.
2. Single quoted strings are supported and work just like double
quoted strings.
3. The peg parser won't actually accept backquoted strings (I don't
think)

Fixes: #411
2020-05-29 07:58:50 -05:00
tgruben
c177bf831d
Merge pull request #409 from tgruben/transaction-doc-update
correction to endpoint
2020-05-29 07:22:18 -05:00
tgruben
242b3d4b14
Merge branch 'master' into transaction-doc-update 2020-05-29 07:02:02 -05:00
seebs
6aa5041de6
Merge pull request #313 from seebs/roaring4g
Handle file sizes over 4GB
2020-05-28 22:55:24 -05:00
Seebs
1ca9435af9 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-05-28 17:08:32 -05:00
Todd Gruben
4d1ce90b32 correction to endpoint 2020-05-28 15:36:00 -05:00
tgruben
a777eddfcf
Merge pull request #405 from tgruben/trace-tagging
added some context to tracing
2020-05-28 13:34:19 -05:00
tgruben
5cd15b250a
Merge branch 'master' into trace-tagging 2020-05-27 15:46:51 -05:00
Todd Gruben
4274d2d141 convert to camelCase 2020-05-27 15:23:13 -05:00
Kuba Podgórski
6ed3bde54e
Merge pull request #407 from kuba--/status
Add grpc uri to status
2020-05-27 17:26:32 +02:00
Kuba Podgórski
604f3b3373 Add grpc uri to status 2020-05-27 16:41:38 +02:00
Jaden Weiss
e0291e9d25
Merge pull request #398 from jaddr2line/transactionmetrics
add metrics for transactions
2020-05-27 08:52:53 -04:00
Jaden Weiss
efef42ae97
Merge branch 'master' into transactionmetrics 2020-05-27 08:36:23 -04:00
Todd Gruben
022019c6cc removed shard level tracing tag 2020-05-26 23:23:57 -05:00
Travis Turner
ffa40b1bdb
Merge pull request #387 from travisturner/int-eq-null
Add support for `intfield == null`
2020-05-26 21:05:42 -05:00
Todd Gruben
a2f825a32e added some context to tracing 2020-05-26 17:18:23 -05:00
Jaden Weiss
a4643084bd
Merge branch 'master' into transactionmetrics 2020-05-26 17:55:12 -04:00
Jaden Weiss
5644fb2275
add metrics for transactions 2020-05-26 17:51:28 -04:00
Travis
e4b9293f26
Add support for int == null 2020-05-22 12:29:52 -05:00
Travis Turner
d36f397a35
Merge pull request #404 from travisturner/row-todos
clean up the TODOs and some comments
2020-05-22 12:05:58 -05:00
Travis
041726fbf7
clean up the TODOs and some comments 2020-05-22 11:00:22 -05:00
Travis Turner
2586661812
Merge pull request #402 from travisturner/roaring-tests
Address TODOs in roaring tests
2020-05-21 19:50:38 -05:00
Travis
0a94f8393f
Address TODOs in roaring tests
In addition to adding some tests, this commit moves the
`GenerateUint64Slice()` helper function into  a new `generator` package
so that it can be used in both internal and non-internal tests.
2020-05-21 13:28:54 -05:00
Jaden Weiss
c04143fd61
Merge pull request #394 from jaddr2line/nextdelete
fix use-after-free in b-tree bitmap update
2020-05-20 13:39:05 -04:00
alisharawal
aa0cfecdb3
Update README.md 2020-05-20 11:37:22 -05:00
Jaden Weiss
6e3e513425
roaring: fix use-after-free in b-tree bitmap update 2020-05-20 12:01:21 -04:00
Travis Turner
8eae053fe6
Merge pull request #395 from travisturner/roaring-todos
clarify a few of the TODO comments
2020-05-19 15:16:05 -05:00
Travis
631d3deeed
clarify a few of the TODO comments 2020-05-19 13:50:48 -05:00
Travis Turner
4b4fd590ca
Merge pull request #389 from travisturner/proto-todos
finish implementing PairField proto encoding
2020-05-19 08:54:58 -05:00
Travis
4fb3820afb
finish implementing PairField proto encoding 2020-05-18 20:19:22 -05:00
Travis Turner
231fef27eb
Merge pull request #390 from travisturner/deadline-skew
increase test deadlineSkew to 1s
2020-05-18 20:18:51 -05:00
Travis
42814bb70c
increase test deadlineSkew to 1s 2020-05-18 19:57:44 -05:00
Travis Turner
63dd5e1174
Merge pull request #386 from travisturner/bsigroup-edges
Fix edge case bugs in range queries
2020-05-18 15:02:50 -05:00
Travis
d0de49ef39
handle edge cases in range queries 2020-05-16 10:35:35 -05:00
seebs
c6d61391d2
Merge pull request #249 from seebs/roaringrow
use roaring row support internally
2020-05-15 17:00:17 -05:00
Seebs
0ddc968001 cache result of marshalling import-was-OK message
This message gets generated millions of times and it's unchanging
for the life of the program, and small.
2020-05-15 16:22:08 -05:00
Seebs
79940cf077 encoding/proto: allow distinct serializers
We want to be able to control whether or not we use roaring to
serialize Rows, which means serializers have to be able to be
distinct.

We also make corresponding changes to http/handler.go to have
it use the exported serializers directly rather than the API's
serializer (which is always the base protobuf serializer
right now, and if it weren't, that would be bad because we
were assuming it was).

When we're accepting protobuf from a pilosa server, flag that
we'll accept roaring bitmaps as opposed to the naive column
representation.
2020-05-15 16:22:08 -05:00
Seebs
ce0761050e less spammy snapshotqueue
During testing we spawn a lot of tiny snapshot queues. Make the message
less spammy by printing it only if any enqueues were skipped (shouldn't
ever happen) or more than one thing got enqueued (likely in real usage,
but doesn't happen in testing usually).
2020-05-15 16:22:08 -05:00
Kuba Podgórski
3151d83136
Merge pull request #383 from kuba--/grpc-err/356
Wrap grpc resp.Err
2020-05-15 23:14:41 +02:00
Kuba Podgórski
3fe85d0f91 Move grpc_internal_test to grpc_test 2020-05-15 19:52:03 +02:00
Kuba Podgórski
ea08cce8fe
Update api.go
Co-authored-by: Travis Turner <travis@pilosa.com>
2020-05-15 19:39:36 +02:00
Kuba Podgórski
f40601f6f5 Wrap grpc resp.Err 2020-05-15 18:16:31 +02:00
Kuba Podgórski
e39334ca92
Merge pull request #377 from kuba--/opt-indiagnostics/310
Disable diagnostics by default
2020-05-15 02:09:31 +02:00
Kuba Podgórski
7ee8f80012
Merge branch 'master' into opt-indiagnostics/310 2020-05-15 00:53:33 +02:00
Kuba Podgórski
fc9e75edc2
Merge pull request #378 from kuba--/off-ae/340
Turn anti-entropy off by default
2020-05-13 14:26:13 +02:00
Kuba Podgórski
fd27cbb886
Update server/config.go
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2020-05-12 18:51:53 +02:00
Kuba Podgórski
889f79d11a Turn anti-entropy off by default 2020-05-12 16:49:43 +02:00
Kuba Podgórski
368cb8cb53 opt-in diagnostics 2020-05-12 15:37:47 +02:00
Travis Turner
2f44a16755
Merge pull request #374 from travisturner/todo-fixes
tidy up some of the TODO comments
2020-05-10 21:45:13 -05:00
Travis
bc8244a581
well, put the TODO back, just in a different place 2020-05-10 19:18:54 -05:00
Travis
d546b8ac01
use pilosa.ErrNotImplemented for unused interface implementations 2020-05-10 18:50:05 -05:00
Travis
9255d43e9a
tidy up some of the TODO comments 2020-05-09 22:26:12 -05:00
Cody Soyland
16f0b5eaba
Merge pull request #343 from codysoyland/branch-rename
Rename enterprise branch to master
2020-05-08 17:50:02 -05:00
Cody Soyland
b96666d06a Rename enterprise branch to master 2020-05-08 16:29:17 -05:00
Kuba Podgórski
5578eb8daa
Merge pull request #258 from kuba--/intersect-inplace
The first implementation of intersect in place
2020-05-07 11:23:40 +02:00
Kuba Podgórski
c802caeddd The first implementation of intersect in place 2020-05-06 23:59:07 +02:00
Kuba Podgórski
1a00008dbd
Merge pull request #339 from kuba--/getridof-rowid
get rid of rowID from groupby on ints response
2020-05-06 23:43:56 +02:00
Kuba Podgórski
19df3211f9 get rid of rowID from groupby on ints response 2020-05-06 23:23:43 +02:00
Travis Turner
04f09870ec
Merge pull request #338 from travisturner/remove-lookup
remove extra index lookup
2020-05-06 13:54:18 -05:00
Travis
2ca4e971f1
remove extra index lookup 2020-05-06 13:04:46 -05:00
Travis Turner
994ac5aad8
Merge pull request #337 from travisturner/fieldvalue
add FieldValue call
2020-05-06 12:29:39 -05:00
Travis
a91014c7bb
add FieldValue call 2020-05-06 11:52:27 -05:00
Travis Turner
a72de2c68a
Merge pull request #329 from travisturner/cluster-startup
avoid deadlock on translationSync.Reset during startup
2020-05-05 08:56:23 -05:00
Travis
92a94c9ec1
remove noSleep option 2020-05-05 08:31:43 -05:00
Travis
7b36f417d8
avoid deadlock on translationSync.Reset during startup 2020-05-05 08:31:42 -05:00
Travis Turner
f9cb7abccf
Merge pull request #334 from travisturner/block-limits
Fix off-by-one maxRowID in block limits
2020-05-04 14:02:30 -05:00
Travis
de0785d305 add a test for the "clears" bug 2020-05-01 16:15:42 -05:00
Travis
1f308066a7 fix test error messages 2020-05-01 15:54:56 -05:00
Travis
b25796f532 Fix off-by-one maxRowID in block limits
In the case where a block merge needed to occur
on a replica containing a row on the edge of the block,
the existing logic would inadvertently clear the first
row in the next block. This PR fixes that.
2020-05-01 15:15:47 -05:00
Matthew Jaffee
8e0a787ec0
Merge pull request #332 from jaffee/tracing-off
change default tracing config to 'off'
2020-04-30 21:25:02 -05:00
Matt Jaffee
8aa7a76d31
change default tracing config to 'off'
also fix a typo
2020-04-30 15:02:15 -05:00
Cody Soyland
ea99f32d36
Merge pull request #327 from codysoyland/docker-bind-grpc
Bind to public interface in docker image
2020-04-28 14:45:06 -05:00
Cody Soyland
0c7a83dc0b Bind to public interface in docker image 2020-04-28 14:20:22 -05:00
Travis Turner
95d44dce28
Merge pull request #318 from travisturner/config-cmd
suppress test config arguments from pilosa config output
2020-04-24 13:23:36 -05:00
Travis
9405463911 suppress test config arguments from pilosa config output 2020-04-24 11:02:42 -05:00
Travis Turner
022b135538
Merge pull request #316 from travisturner/json-header
Ensure content-type header is application/json where appropriate
2020-04-23 22:10:44 -05:00
Travis
af6eb94c1d increase deadlineSkew so TestTransactionsAPI doesn't fail during race test 2020-04-23 17:26:35 -05:00
Travis
5da907d469 ensure content-type header is application/json where appropriate 2020-04-23 16:24:40 -05:00
Travis Turner
8cf06bf5d9
Merge pull request #314 from travisturner/decimal-adjust-precision
Adjust decimal precision if we have decimal places to sacrifice.
2020-04-23 08:43:23 -05:00
Travis
432e18d571 return early on mantissa=0 2020-04-22 19:11:23 -05:00
Travis
809a02d986 Adjust decimal precision if we have decimal places to sacrifice. 2020-04-22 17:10:05 -05:00
Travis Turner
2795a3f7e2
Merge pull request #309 from molecula/transactions
Transactions
2020-04-22 15:52:42 -05:00
Matt Jaffee
97ae8e0db7
add kuba testcase, fix race
we fix the race by not returning pointers to the things which we're
keeping in the in-memory store
2020-04-22 15:17:25 -05:00
Matt Jaffee
85f57f9975
fix lint 2020-04-22 14:30:14 -05:00
Matt Jaffee
7c7836f16f
convert transactions to be pointers everywhere
I think this will improve the transaction response messages Kuba
mentioned where it was an empty transaction instead of a nil or not
there... if not it should make it easier to do that anyhow.
2020-04-22 14:01:24 -05:00
Matt Jaffee
9dbc6f89db
address minor feedback from previous PR 2020-04-22 12:31:25 -05:00
Matt Jaffee
7da137277c
tweak comment, add validation TODO 2020-04-22 10:42:59 -05:00
Matthew Jaffee
afcb3e7f96
Merge pull request #2 from travisturner/backups
minor code adjustments during review
2020-04-22 07:35:05 -05:00
Travis Turner
c9b7ed51aa
Update deadline comment
Co-Authored-By: Matthew Jaffee <matthew.jaffee@gmail.com>
2020-04-21 17:49:57 -05:00
Travis
08583cf2d0 minor code adjustments during review 2020-04-21 16:54:17 -05:00
Matt Jaffee
a3c5f4822e
keep the zone info back in deadline strings (but output in UTC)
instead of defining them as being in UTC, but not including the zone
info, we will keep the standard format with zone info, but always
output the time in UTC. This means that we can parse incoming
deadlines that happen to have zone information, though I don't think
we ever need to.
2020-04-21 12:29:19 -05:00
Matt Jaffee
5e29effa93
don't wrap error, dedup compare transactions code 2020-04-20 22:30:14 -05:00
Matt Jaffee
b23d27f507
add cluster state validation to API methods for transactions 2020-04-20 22:22:40 -05:00
Matt Jaffee
662ed4f324
invert if statements and fix typos 2020-04-20 22:12:07 -05:00
Matt Jaffee
432ab57822
add license headers 2020-04-20 14:41:05 -05:00
Matt Jaffee
89c1d48a0f
transaction deadline format UTC, lint
also change "deadlineSkew" comparison in tests to account for race tests in CI
seeing false differences
2020-04-20 14:37:28 -05:00
Matt Jaffee
c36952a0f1
propagate context throughout transaction stuff 2020-04-20 13:30:48 -05:00
Matt Jaffee
41975de6b8
add transactions external documentation
- make sure client reads/closes all bodies
- support blank transaction ID in http handler
2020-04-20 13:30:48 -05:00
Matt Jaffee
210c7239ab
add HTTP handlers and client for transactions 2020-04-20 13:30:48 -05:00
Matt Jaffee
9ad1106647
implement transaction API layer and intra-cluster messaging
also adds a "noSleep" option to the server command to avoid the 5
second sleep we introduced on startup for non-coordinator cluster
nodes. The sleep doesn't seem to be needed in the tests and makes them
much slower.
2020-04-20 13:30:48 -05:00
Matt Jaffee
088e60b830
better defer that Unlock 2020-04-20 13:30:48 -05:00
Matt Jaffee
38cec6f20e
add TransactionManager and TransactionStore for transactions/backups
This all needs to be wired into API/Server/Cluster/Holder etc. but I
think the TransactionManager will be a pretty good building block for
managing transaction state at the coordinator level.
2020-04-20 13:30:48 -05:00
Seebs
c3ef9a1768
draft outline of transaction API 2020-04-20 13:30:47 -05:00
Cody Soyland
a353527705
Merge pull request #307 from codysoyland/copy-reopen
Copy reopen.FileWriter into pilosa
2020-04-20 12:41:09 -05:00
Cody Soyland
761b090f3c Fix linter error 2020-04-20 12:10:44 -05:00
Cody Soyland
5e1c72e6f2 Copy reopen.FileWriter into pilosa 2020-04-20 11:58:09 -05:00
Travis Turner
53500e5ad5
Merge pull request #304 from travisturner/grpc-listener
move gRPC listener creation outside of grpcServer
2020-04-18 13:14:12 -05:00
Travis
7de8399b17 move gRPC listener creation outside of grpcServer
For tests, we need to create the grpc listener with port 0 in order to
automatically assign a port. This PR moves the lister creation outside
of the grcpServer itself so that we can access that auto-created port.
2020-04-18 11:38:15 -05:00
Travis Turner
72d496f5c7
Merge pull request #302 from travisturner/grpc-client-queryunary
add QueryUnary to the grpc client api
2020-04-17 16:32:41 -05:00
Travis
2b98ef5edb add QueryUnary to the grpc client api 2020-04-17 16:12:10 -05:00
seebs
26091bd3ed
Merge pull request #301 from codysoyland/makefile-checkptr
Use makefile variable for NOCHECKPTR
2020-04-17 15:57:33 -05:00
Cody Soyland
3b5908332d Use makefile variable for NOCHECKPTR 2020-04-17 15:15:43 -05:00
seebs
f8f924e972
Merge pull request #300 from seebs/groupby
GroupBy should terminate even if the last result is empty
2020-04-17 15:13:49 -05:00
Seebs
3a7ab3b8eb GroupBy should terminate even if the last result is empty
If you have two criteria, and the last result you generate is
empty, the nextAtIdx iterator for i==1 will try to continue
poking the i==0 iterator. That one produces a nil result, and
declares the entire group-by iterator done... But the nextAtIdx
call above it isn't checking that, and just loops forever.
This causes some queries to become stuck permanently, consuming
ridiculous amounts of resources almost entirely focused on
calling Intersect millions of times to get empty results.
2020-04-17 14:39:03 -05:00
Cody Soyland
398ce117ec
Merge pull request #287 from codysoyland/logger
Reopen log file on SIGHUP
2020-04-17 12:40:25 -05:00
Cody Soyland
1058440cfe Do not reuse error object (data race) 2020-04-16 17:08:50 -05:00
Cody Soyland
e4cd1b8871 Add -v flag to test-race 2020-04-16 17:08:50 -05:00
Cody Soyland
a00e93f699 Add TODO about fork 2020-04-16 17:08:50 -05:00
Cody Soyland
2155d6cab8 Move some things around, fix linter warnings. 2020-04-16 17:08:50 -05:00
Cody Soyland
a66ee26a6b Reopen log file on SIGHUP 2020-04-16 17:08:50 -05:00
Cody Soyland
08fa90e0f3 Reduce duplication of setupLogger arch-specific code 2020-04-16 17:08:50 -05:00
Travis Turner
46fb6859ed
Merge pull request #296 from travisturner/grpc-tabler-rowser
gRPC tabler rowser
2020-04-16 15:19:47 -05:00
Travis
c45a4bf3dc ToTable and ToRows interface for gRPC 2020-04-16 14:16:54 -05:00
Travis Turner
0691b6c015
Merge pull request #294 from travisturner/overflow-fix
error on potential overflow
2020-04-15 16:24:37 -05:00
Travis
80f1bdebd7 error on potential overflow 2020-04-15 15:50:03 -05:00
Travis Turner
468b69fba9
Merge pull request #291 from travisturner/range-problems
fix some range query problems
2020-04-15 15:27:12 -05:00
Travis
8a22a3ede3 fix some range query problems 2020-04-15 14:42:16 -05:00
Travis Turner
37f05fc3ea
Merge pull request #288 from travisturner/upgrade-min-max
upgrade decimal min/max with scale
2020-04-15 08:08:00 -05:00
Travis
79a6c1e5ab upgrade decimal min/max with scale 2020-04-15 00:14:07 -05:00
seebs
f41bced2ec
Merge pull request #286 from seebs/storeauto
in Store/SetRow, create field if it doesn't already exist
2020-04-14 15:33:10 -05:00
Seebs
70bfe86f75 in Store/SetRow, create field if it doesn't already exist
If you try to Store to a nonexistent field, we create an automatic
Set field with no cache for it, assuming it won't be used for TopN
queries. If you want TopN to work, you need to actually create it
yourself.
2020-04-14 15:12:36 -05:00
alanbernstein
18d01dd62a
Merge pull request #280 from alanbernstein/snake-case-node
Snakify
2020-04-11 13:25:58 -05:00
Alan Bernstein
615c1bd186 Snakify 2020-04-10 22:15:43 -05:00
Matthew Jaffee
76404142ba
Merge pull request #246 from molecula/prometheus-improvements
Prometheus improvements
2020-04-10 21:55:35 -05:00
Matt Jaffee
68276159ca
don't access req.Query before knowing req is a QueryRequest 2020-04-10 21:07:43 -05:00
Alan Bernstein
18c6d8f76f
Update a few metric names 2020-04-10 20:59:20 -05:00
Alan Bernstein
71b9762501
Address review feedback again 2020-04-10 20:59:20 -05:00
Alan Bernstein
9947c92e8e
Add stats labels and slow-query log in GRPC endpoints 2020-04-10 20:59:20 -05:00
Alan Bernstein
eaf21eb19b
Add metrics for GRPC request timing 2020-04-10 20:59:19 -05:00
Alan Bernstein
5df680fb9f
Remove old metric from tests 2020-04-10 20:59:19 -05:00
Alan Bernstein
d79f04b7b3
Remove MetricMaximumRow 2020-04-10 20:59:19 -05:00
Alan Bernstein
a7bfacbee2
Revert "Add tags to MaxRow metric"
This reverts commit 6013e7211b3aef93d0880401c8ef74b34a620328.
2020-04-10 20:59:19 -05:00
Alan Bernstein
b37a0addb3
Add tags to MaxRow metric 2020-04-10 20:59:19 -05:00
Alan Bernstein
b1838159f2
Minor fixes 2020-04-10 20:59:19 -05:00
Alan Bernstein
df2503dfa6
Switch to Timing helper function 2020-04-10 20:59:19 -05:00
Alan Bernstein
2423ecf8d5
Update some metric names to follow conventions better 2020-04-10 20:59:19 -05:00
Alan Bernstein
f883d61c28
Consolidate BlockRepair metrics with tags 2020-04-10 20:59:18 -05:00
Alan Bernstein
389acfc8ed
Fix minor issues with metric labels and tests 2020-04-10 20:59:18 -05:00
Alan Bernstein
c2c0a5c32f
Address review feedback 2020-04-10 20:59:18 -05:00
Alan Bernstein
8b405c226c
Add 'prometheus' option in other help text/comments 2020-04-10 20:59:18 -05:00
Alan Bernstein
a3fb1c022b
Use metrics consts in tests 2020-04-10 20:59:18 -05:00
Alan Bernstein
8c9db373d0
Fix some metrics names 2020-04-10 20:59:18 -05:00
Alan Bernstein
5137f56f9c
Use const from package 2020-04-10 20:59:18 -05:00
Alan Bernstein
34c6d42063
Fix broken metrics label and log when others are encountered 2020-04-10 20:59:17 -05:00
Alan Bernstein
3c275681d2
Profile -> Column 2020-04-10 20:59:17 -05:00
Alan Bernstein
b1adcd91fc
Use consistent metric name convention 2020-04-10 20:59:17 -05:00
Alan Bernstein
70111b5604
Define metrics names as constants 2020-04-10 20:59:17 -05:00
Alan Bernstein
84e6a25bad
Update help message 2020-04-10 20:59:17 -05:00
Alan Bernstein
857ddf73c2
Reduce snapshot verbosity 2020-04-10 20:59:17 -05:00
Alan Bernstein
eceef6b42b
Use 'query_' prefix to identify query metrics 2020-04-10 20:59:16 -05:00
tgruben
550fcec9ee
Merge pull request #279 from tgruben/fix-closers
Closed all post request bodies and optimized available shard with new view capabilities
2020-04-10 20:29:04 -05:00
Todd Gruben
ccc7ca3aa5 close not needed 2020-04-10 20:12:32 -05:00
Todd Gruben
5590f1d954 lint fix 2020-04-10 19:07:01 -05:00
Todd Gruben
ef5a8cefef Added request Close and optimized availble shard with new view capabilities 2020-04-10 17:59:44 -05:00
seebs
4325d62fe7
Merge pull request #277 from seebs/between
Return empty rows for impossible ranges
2020-04-10 16:21:09 -05:00
Seebs
017e65cd99 Return empty rows for impossible ranges
If the high end of a range is below the low end of the range, there's
no values in it, so we can short-circuit that. If we don't, if the
low end is zero or higher, and the high end is below zero, we can
get very surprising behaviors, such as accepting values up to the
inverse of the high end. Add a test case for this and treat it the
same as a low range end above the field's maximum or a high end
below the field's minimum, returning an empty row immediately.
2020-04-10 13:24:08 -05:00
seebs
9b002bcc24
Merge pull request #271 from seebs/decimalfault
Handle nonexistent shards in min/max decimal queries.
2020-04-09 22:01:07 -05:00
Seebs
8e662d33a5
Handle nonexistent shards in min/max decimal queries.
If a shard has never had any decimal values in it at all for a
field, the ValCount object returned has no DecimalVal, which could
cause a segfault if we don't check for it. Add a test case which
sporadically triggers that behavior (it's timing/luck related,
unfortunately), and then also fix it.
2020-04-09 21:30:34 -05:00
Matthew Jaffee
179cab91e7
Merge pull request #275 from travisturner/serialize-null
serialize null operation (!= null)
2020-04-09 21:25:05 -05:00
Travis
88b2d79812 serialize null operation (!= null) 2020-04-09 17:56:27 -05:00
alanbernstein
0e6ed80bd4
Merge pull request #269 from alanbernstein/long-query-full
WIP Show full query string when logging slow queries
2020-04-09 16:12:11 -05:00
Alan Bernstein
92416018d5
Use more general log message 2020-04-09 15:53:40 -05:00
Alan Bernstein
5aebb242f8
Fix off-by-one error 2020-04-09 15:53:40 -05:00
Alan Bernstein
e3ace544ca
Show full query string when logging slow queries 2020-04-09 15:53:39 -05:00
tgruben
57b2f32fa1
Merge pull request #260 from tgruben/sync-start
delay start for non-coordinator
2020-04-09 14:42:41 -05:00
Todd Gruben
e7bbc3a0a8 Added delay to allow cooridinator a head start in launch on multi node clusters.
considered using Cluster.Disabled to identify if pilosa was stand alone but settled
on using an empty gossip seeds list
2020-04-09 14:20:01 -05:00
alanbernstein
bdfad719df
Merge pull request #263 from alanbernstein/grpc-multi
Support multiple dialTargets and cycle through on connection reset
2020-04-08 13:39:58 -05:00
alanbernstein
1846d21765
Merge pull request #1 from travisturner/dialtargets
cycle through dial targets regardless of error
2020-04-08 12:55:17 -05:00
Travis
8f0ae1b6f5 cycle through dial targets regardless of error 2020-04-08 12:29:15 -05:00
Alan Bernstein
adb21589f0 Support multiple dialTargets and cycle through on connection reset 2020-04-08 10:09:49 -05:00
seebs
1b5d86c8f0
Merge pull request #240 from seebs/q2perf
improve performance of difference/not
2020-04-07 20:24:51 -05:00
Seebs
be379e7806 cache AvailableShards
The computation of available shards is cheap, because realistically, virtually
no one has enough shards that the resulting bitmap is more than one container.

We don't try to fix this at the field/index levels because it's significantly
harder to do there, but I think the creation of these bitmaps is probably
the most expensive part, and switching the unions to union-in-place probably
reduces cost significantly.

Note that the bitmaps being unioned almost certainly have exactly one small
container in them.
2020-04-07 19:33:21 -05:00
Seebs
6c797e0c4e TODO => TODONE: use masks for runToBitmap
Had the code lying around from mad science elsewhere, backported.
2020-04-07 19:33:21 -05:00
Seebs
d4e496887b make differenceRunBitmap smarter
We avoid using bitmapContains so often because that turns out to be expensive.
Also, if we produce more than runMaxSize runs, we're going to convert to
a bitmap container (or possibly an array container if there were over
2048 items, but they're all singletons), and we can streamline that by just
converting the source to bitmap and returning differenceBitmapBitmap, which
is faster in this case.

This appears to overall take about half as long in the workload I was
looking at.
2020-04-07 19:33:20 -05:00
Kuba Podgórski
7868188670
Merge pull request #200 from kuba--/groupby-int/124
Group by on ints
2020-04-08 01:47:17 +02:00
Kuba Podgórski
1217deee1c Rebase 2020-04-08 01:06:18 +02:00
tgruben
64caffebe8
Merge pull request #196 from tgruben/async-available-shards
limit frequency of writes for available shards broadcast
2020-04-06 09:08:04 -05:00
Todd Gruben
6712f8cf06 removed debug log 2020-04-06 08:43:30 -05:00
Todd Gruben
5470753cb5 fix conflict 2020-04-05 18:37:11 -05:00
Travis
0e2bb550db add deleted (rebalanced) shards to remoteAvailableShards 2020-04-05 18:37:11 -05:00
Todd Gruben
6bd81b87eb unexport availableShardFileFlushDuration 2020-04-05 18:37:11 -05:00
Todd Gruben
000ea90877 unbuffer channel 2020-04-05 18:34:43 -05:00
Todd Gruben
af068e08e7 cleanup and comments 2020-04-05 18:34:43 -05:00
Todd Gruben
40a3dce93c Co-authored-by: Travis Turner <github@calfrope.com> 2020-04-05 18:34:43 -05:00
Todd Gruben
bb04f7f6ac limit frequency of writes for available shards 2020-04-05 18:31:28 -05:00
Cody Soyland
0a86f6a97b Increase gRPC maximum message length 2020-04-03 16:35:57 -05:00
Travis
b7fcfb41d9 add proto OldMin/OldMax for backward compatibility 2020-04-03 12:25:07 -05:00
Travis Turner
48879107b0
Merge pull request #244 from travisturner/fix-race
make sure frag.maxRow() call is lock-protected
2020-04-02 23:52:38 -05:00
Travis
b4f1781d30 make sure frag.maxRow() call is lock-protected 2020-04-02 23:25:57 -05:00
seebs
632f6856ab
Merge pull request #229 from seebs/checkptr
disable checkptr with go 1.14
2020-04-02 22:19:45 -05:00
seebs
a20532073b
Merge branch 'enterprise' into checkptr 2020-04-02 20:48:49 -05:00
alanbernstein
4faacad4cf
Merge pull request #242 from molecula/prometheus-options
Add options to prometheus client to support setting namespace
2020-04-02 20:24:15 -05:00
Alan Bernstein
dad4ccf103 Propagate namespace to tags client 2020-04-02 19:29:46 -05:00
Alan Bernstein
110d2b6024 Restore lost comment 2020-04-02 19:07:43 -05:00
Alan Bernstein
f15d031c55 Add options to prometheus client to support setting namespace 2020-04-02 19:05:55 -05:00
Travis Turner
7432546af8
Merge pull request #241 from travisturner/shardwidth22-tests
alter tests to allow for shardwidth22
2020-04-02 18:25:29 -05:00
Travis
182c1d3c42 alter tests to allow for shardwidth22
also, reset BitDepth on field and bsiGroup during
importRoaringOverwrite
2020-04-02 17:32:49 -05:00
Cody Soyland
da503776e2
Merge pull request #237 from codysoyland/ci-tweaks
CI: Modify Docker Hub rules and use "make test-race" for running race detector
2020-04-02 12:25:40 -05:00
Cody Soyland
6a639efdba Modify Docker Hub deployment filter rules.
The documentation is unclear/incorrect, and these filters aren't
behaving correctly. This is an attempt at fixing that. More info at:
https://discuss.circleci.com/t/job-runs-even-when-tags-ignore-filter-is-triggered-when-combined-with-branches-only/20664/11
2020-04-02 12:14:37 -05:00
Cody Soyland
14319cc54b Use "make test-race" instead of custom test flags in CI 2020-04-02 12:14:37 -05:00
Seebs
c6799bd604 disable checkptr with go 1.14
The checkptr feature is actually probably right about a few
things in roaring and boltdb, but we can ignore them for now, and
that prevents checking for races, so we disable that temporarily.

Also supply NOCHECKPTR in non-race tests because CI uses "make test"
with -race in $TESTFLAGS and we might do that on other occasions.
2020-04-02 11:37:06 -05:00
Matthew Jaffee
44fcbee447
Merge pull request #235 from jaffee/nil-check-indexmeta
add nil check for index meta
2020-04-02 11:33:25 -05:00
Matt Jaffee
35fa26918d
add nil check for index meta 2020-04-02 11:09:07 -05:00
Travis Turner
794bc5b168
Merge pull request #232 from travisturner/decimal-grcp
convert grpc response to use pql.Decimal
2020-04-02 07:55:26 -05:00
Travis
4d985653ae convert grpc response to use pql.Decimal 2020-04-01 23:59:50 -05:00
Travis Turner
0b480f8405
Merge pull request #231 from travisturner/reintroduce-decimal
Reintroduce decimal
2020-04-01 21:44:26 -05:00
Travis
22cca67d6a Revert "back out the pql.Decimal changes"
This reverts commit 741ba9b268.
2020-04-01 17:46:46 -05:00
Matthew Jaffee
e77bf45643
Merge pull request #227 from travisturner/backout-decimal
back out the pql.Decimal changes
2020-04-01 11:32:02 -05:00
Travis
741ba9b268 back out the pql.Decimal changes 2020-04-01 11:10:33 -05:00
Cody Soyland
1284791d22
Merge pull request #224 from codysoyland/ci-fixes
CI fixes: quote TESTFLAGS and fix stable release filter
2020-04-01 09:41:38 -05:00
Cody Soyland
dc5a471939 Downgrade golangci-lint to 1.23.8 (attempt fix for OOM failures) 2020-04-01 09:07:11 -05:00
Cody Soyland
39d83e7b6f Add no_output_timeout for the race detector 2020-04-01 09:07:11 -05:00
Cody Soyland
01033d4fff CI fixes: quote TESTFLAGS and fix stable release filter 2020-04-01 09:07:11 -05:00
Kuba Podgórski
b0f1ee3fce
. (#225) 2020-04-01 15:19:05 +02:00
seebs
c6083d6816
Merge pull request #163 from seebs/distinctshards
Address issues with Distinct failures in testing, or across shards, or in cases where the range of Distinct results is not the same as the range of shards available in any index.
2020-03-31 21:06:16 -05:00
Travis
0374bda45f Adjust bare-distinct logic.
If an index is provided to a bare distinct which happens
to be the index handling the query, then the query needs
to behave as if no index argument was provided.

For example:

When querying against index `i`,
```
Distinct(index="i", field="ints")`
```
should behave exactly like
```
Distinct(field="ints")
```
2020-03-31 19:51:06 -05:00
Seebs
a495b6c227 make Distinct work across nodes, probably
Problem: A top-level bare "Distinct" call returns results only
for shards on the current node.

Analysis: We don't actually want to limit Distinct calls to "available"
shards at all. We just want to run them on everything. But we already
did that in generating the precomputed results; all we need to do is,
if we get a non-shard-specific request for precomputed values, just
return all the values.

It's pretty hard to create logic for this using our fancy mapReduce,
but also we could just... not do that.
2020-03-31 19:51:06 -05:00
seebs
12ba11a437
Merge pull request #215 from seebs/mmap-v-cache
clear container lookup cache when updating every container, handle nils with differenceInPlace, use transaction/ops log for mergeBlock.
2020-03-31 19:49:43 -05:00
Seebs
76e7470559 make mergeBlock use transactions
mergeBlock was bypassing the transaction setup stuff, which means that
if we ran out of open files, mergeBlock wouldn't generate ops log
entries (!), also it didn't update the cache (!). This came up because
it also didn't enjoy the "catch your segfaults and issue a diagnostic"
behavior offered by the generation code.

Switch to computing positions directly and calling importPositions,
which does a transaction.
2020-03-31 16:22:41 -05:00
Seebs
28b9d6d7fc ditch lastKey cache on UpdateEvery
UpdateEvery can change every key, and I think it strongly suggests no
reasonable expectation of repeated access to a previously-accessed key,
but also it can change the containers and replace them.

We were avoiding caching mapped containers in some but not all cases,
and that was causing segfaults. But really, the *problem* is that
the remap operation wasn't clearing (or updating) the cache. Cleaning
that up allows us to take advantage of the caching performance advantage
even when working with read-only/mapped bitmaps.

The only way to hit this:

* Have mmapped containers to begin with.
* Do reads so those containers get frozen.
* Access, either reading or writing, a specific container with key K.
* Snapshot, so the bitmap gets its containers replaced.
* Remember, they have to be frozen -- if they aren't frozen,
  we'll update the containers in place.
* Now have GC run so it actually unmaps the data.
* Now try to write to the container with key K *before reading or
  writing any other key*. You have to get through the whole snapshot
  and GC process without any other reads or writes.
* You get the cached value. You try to use it. You explode.

The sliceContainers code was also setting lastKey to 0 in some cases,
but also setting lastContainer to nil, so this wouldn't have caused
problems, but just to be careful, I've standardized on ^uint64(0)
for everything.
2020-03-31 16:20:05 -05:00
Seebs
1ac00291f3 Add test for the weird remapping/cache interaction.
This test is really a test of a very specific bit of the internals
of containers_btree/containers_slice, but we can't easily test it from
there because they don't have all the logic for remapping files.

The underlying issue is that they maintain a single-item "most recent
container" cache, and this wasn't getting updated during the remap
operations, happening through containers.UpdateEvery. The fix is
probably just to make sure that UpdateEvery invalidates the cache.
2020-03-31 16:20:05 -05:00
Seebs
d26e221a91 don't call isArray on a nil *Container
differenceInPlace wasn't checking for nil containers, which are
theoretically valid empty containers. Also added a couple of other
N==0 checks to streamline the higher-level operation.
2020-03-31 16:20:05 -05:00
Cody Soyland
3b6a26e5c6
Merge pull request #219 from codysoyland/ci-updates
Add updated CircleCI config
2020-03-31 16:18:10 -05:00
Cody Soyland
3a7f385a01 Add updated CircleCI config
- Remove YAML magic
- Remove a lot of duplication
- Update linter
- Use parameterized jobs and matrix build
- Update Docker Hub CD to produce versioned and "latest" images
- Add custom shard width test to workflow
2020-03-31 15:17:11 -05:00
Travis Turner
b5aa280ced
Merge pull request #220 from travisturner/decimal-yaml
yaml marshal/unmarshal for pql.Decimal
2020-03-31 13:53:00 -05:00
Travis
7cb265098f yaml marshal/unmarshal for pql.Decimal 2020-03-31 12:43:42 -05:00
Kuba Podgórski
6dc3837c9a
WIP: fix 'unknown call: Distinct' error (#213) 2020-03-31 16:29:14 +02:00
Travis Turner
dca2120c06
Merge pull request #199 from travisturner/cluster-resize-translation-partitions
include translate partitions in cluster resize instructions
2020-03-30 22:01:09 -05:00
Kuba Podgórski
ac76f6227d
Make internal.IndexMeta.TrackExistence true 2020-03-30 21:24:16 -05:00
Travis
98c5603965
close reader. include all replias in translation partition rebalance 2020-03-30 21:24:16 -05:00
Travis
4c311aa1a7
write to temp partition file. use io.Copy 2020-03-30 21:24:16 -05:00
Travis
2724ecfd5f
WIP: include translate partitions in cluster resize instructions
This commit adds `TranslationSources` to the cluster
`ResizeInstruction`. These are the sources of translation
partitions which the receiving node needs in order to support
partition distribution in the new, resized cluster.

This also fixes a bug where index options were not being
encode in the proto Index object. That meant that the schema
transferred via protobuf was not correct. The reason why
things normally worked is because index creation typically
happens on the CreateIndex message, which does include the
options.

TODO:

- [ ] implement the TranslateStore interface for `InMemTranslateStore`
and `mock.TranslateStore`
- [ ] surely need some more tests around the `ReadFrom` and `WriteTo`
2020-03-30 21:24:16 -05:00
Travis Turner
2ad06f9423
Merge pull request #212 from travisturner/decimal-min-max-args
support pql.Decimal for decimal field min/max arguments
2020-03-30 14:32:02 -05:00
Travis
80da129861 require scale argument for decimal fields 2020-03-30 13:38:50 -05:00
Travis
1da7cf09bb support pql.Decimal for decimal field min/max arguments 2020-03-27 16:02:47 -05:00
Cory LaNou
2a4088e0ec
Merge pull request #206 from corylanou/test-helpers
Make better use of t.Helper
2020-03-25 07:35:35 -05:00
Cory LaNou
391fda9849
Merge branch 'enterprise' into test-helpers 2020-03-24 15:51:01 -05:00
corylanou
f84185230d
make use of t.Helper 2020-03-24 15:00:32 -05:00
Cody Soyland
7ba5c0e3d3
Merge pull request #201 from codysoyland/queryunary
Add QueryPQLUnary gRPC call
2020-03-23 16:58:27 -05:00
Cody Soyland
1aa1ec51aa Add QueryPQLUnary gRPC call 2020-03-23 16:24:31 -05:00
Cory LaNou
69a1365bf0
Merge pull request #202 from corylanou/sum/194
Fixed sum for negative values
2020-03-23 16:22:11 -05:00
corylanou
f32f9f64a4
fix sum for negative values 2020-03-23 14:02:46 -05:00
Travis Turner
532f746f25
Merge pull request #195 from travisturner/sync-mutex-bool
support mutex/bool fields in anti-entropy
2020-03-19 11:47:37 -05:00
Travis Turner
5cfb29beb2
Merge branch 'enterprise' into sync-mutex-bool 2020-03-19 11:28:56 -05:00
Travis Turner
564eee0bdf
Merge pull request #190 from travisturner/decimal-between
serialize decimal between pql for internode queries
2020-03-19 11:26:12 -05:00
Travis
57c30b9dae support mutex/bool fields in anti-entropy 2020-03-19 11:11:33 -05:00
Travis
4d38723fd4 serialize decimal between pql for internode queries 2020-03-19 07:50:43 -05:00
Travis Turner
419c2179b5
Merge pull request #185 from travisturner/decimal-min-max-overflow
Avoid overflow on decimal min/max default values
2020-03-18 08:01:40 -05:00
Travis
298f290e86
Avoid overflow on decimal min/max default values
If the min/max provided are already on the boundary of int64,
then we don't want to operate on them and cause overflow.
there are still overflow scenarios where a user provides a
min/max which is not on the boundary, but overflow once the
scale is applied. This does not address those cases, but at
least it addresses the default case (where a min/max is not
provided)
2020-03-18 07:41:35 -05:00
Kuba Podgórski
73ca124944
Fix runCountRange when range start == interval start (#181)
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)

Co-authored-by: Pierre Fersing <pierre.fersing@bleemeo.com>
2020-03-17 20:31:35 +01:00
Travis Turner
ba5b133e1e
Merge pull request #180 from travisturner/mu-anti-entropy
add mutex for anti-entropy and node join/leave
2020-03-17 13:05:53 -05:00
Travis
fbbd474978 add mutex for anti-entropy and node join/leave 2020-03-17 12:46:09 -05:00
Travis Turner
22ae1139d1
Merge pull request #172 from travisturner/float-to-decimal
use pql.Decimal instead of float64
2020-03-16 08:35:19 -05:00
Travis
c60241b5a9 Get rid of Sign from pql.Decimal struct
It turns out that it's not very useful to keep the sign
value as a separate argument in the pql.Decimal struct.
This commit incorporates it into Value, and makes Value
an `int64` (for some bone-headed reason I had made it a
`uint32` before which is just dumb).
2020-03-15 23:00:00 -05:00
Travis
30e08eb532 add error conditions to tests 2020-03-15 16:18:59 -05:00
Travis
513edeae9c fix min/max bug for decimal fields 2020-03-14 22:35:24 -05:00
Travis
963affcc30 WIP: use pql.Decimal instead of float64
This commit introduces a new type: pql.Decimal
We use that instead of float64 in order to ensure
that the string representation is consistent.

One unfortunate discovery during implementation is
that the RowAttrs and ColAttrs support floats, and
the PEG file was treating them as such. So I had
to split the PEG definitions into float-specific
items and decimal-specific items.
2020-03-14 22:33:52 -05:00
Travis Turner
334eb3cd08
Merge pull request #175 from travisturner/int-min-max-with-offset
Fixes the min/max bug for `int` fields with offset.
2020-03-14 15:18:48 -05:00
Travis
3863ab4b41 Fixes the min/max bug for int fields with offset.
Methods `MinForShard` and `MaxForShard` were not adjusting
their return value by the offset.
2020-03-14 14:01:40 -05:00
Travis Turner
0d55d6eab2
Merge pull request #160 from travisturner/int-fragment-sync-better-fix
support fragment sync for int and decimal fields
2020-03-13 18:42:12 -05:00
Travis
a5cba75855 fix typos in comment 2020-03-13 12:15:54 -05:00
Travis
3b676a7cbd fix linter warnings 2020-03-13 12:15:54 -05:00
Travis
cbf80370cb support fragment sync for int and decimal fields
This PR adds support for anti-entropy syncing for integer
and decimal fields. It differs from the logic for other
field types in that it does not rely on a consensus to determine
what the value should be; instead, it considers the correct
values to be those of the primary replica. From there, data
is pushed to all non-primary replicas.
2020-03-13 12:15:54 -05:00
Cody Soyland
8b5848f615
Merge pull request #164 from codysoyland/dockerfile-env-config
Use env variables instead of flags in Dockerfile
2020-03-12 14:44:45 -05:00
Cody Soyland
c6a293f818 Use env variables instead of flags in Dockerfile
This allows you to override those attributes without overriding the
entire command.
2020-03-12 11:22:31 -05:00
Travis Turner
93a804f7ab
Merge pull request #165 from travisturner/range-ast-fix
fix Call stringer for range conditional
2020-03-12 08:29:38 -05:00
Travis
0c6f0e2ba5 fix Call stringer for range conditional 2020-03-11 22:53:37 -05:00
Travis Turner
d76e8fc17c
Merge pull request #162 from travisturner/makefile-helpers
add linter and test-race targets to makefile
2020-03-11 10:10:41 -05:00
Travis
dde1e26baa add linter and test-race targets to makefile 2020-03-11 09:24:00 -05:00
Travis Turner
cdbb274a2b
Merge pull request #157 from travisturner/int-fragment-sync-quick-fix
temporary fix for int field replica sync bug
2020-03-09 15:22:41 -05:00
Travis Turner
f747501473
Merge branch 'enterprise' into int-fragment-sync-quick-fix 2020-03-09 14:56:06 -05:00
Matthew Jaffee
d0aad872e2
Merge pull request #144 from jaffee/min-con-reuse
Min con reuse
2020-03-09 14:54:56 -05:00
Matt Jaffee
f0f86500c7
add minimal fix for connection reuse issue - @tgruben has a more complete fix 2020-03-07 09:46:47 -06:00
Travis
70c3cf1775 include a basic test which covers the temp fix 2020-03-05 21:16:10 -06:00
Travis
86da5c7adf temporary fix for int field replica sync bug 2020-03-05 20:57:16 -06:00
Travis Turner
b99bdb8169
Merge pull request #156 from travisturner/forward-translation-to-coordinator
forward field translation request to coordinator
2020-03-05 17:53:35 -06:00
Travis
3e4f7dd3f3 change translateFieldKeys to variadic function 2020-03-05 15:38:34 -06:00
Travis
d06ffd207f forward field translation request to coordinator 2020-03-05 14:54:23 -06:00
seebs
bbeacbe3c3
Merge pull request #147 from seebs/emptylog
don't fill up empty space with non-functional ops logs
2020-03-04 18:28:55 -06:00
Seebs
eb263b7666 don't fill up empty space with non-functional ops logs
Two changes:

1. Don't write batch/roaring adds or removes when N is 0, because
a write of no bits is not a meaningful write.
2. When unmarshalling roaring things, if a roaring bitmap didn't
change many bits, treat it as having changed at least 1 bit per 8 bytes,
so an 8KB hunk of roaring data counts as 1K changes, which will
nudge us towards snapshotting. This should keep us from having
Large Files show up so much.

This was particularly noticeable on the existence field, which
tends to a steady state of "completely full" very quickly in a lot
of cases.
2020-03-04 18:10:10 -06:00
Kuba Podgórski
53c486fce0
Remove not needed translationSyncer from holder. (#152) 2020-03-05 00:19:58 +01:00
Travis Turner
78327904ff
Merge pull request #145 from travisturner/translate-partition-better-fix
add translationSyncer interface
2020-03-03 19:42:50 -06:00
Travis
842c820366 add translationSyncer interface
This PR adds a translationSyncer interface; I tried to include
comments in the code explaining what's going on. This is taken
from those comments:

translationSyncer provides an interface allowing a function
to notify the server that an action has occurred which requires
the translation sync process to be reset. In general, this
includes anything which modifies schema (add/remove index, etc),
or anything that changes the cluster topology (add/remove node).
I originally considered leveraging the broadcaster since that was
already in place and provides similar event messages, but the
broadcaster is really meant for notifiying other nodes, while
this is more akin to an internal message bus. In fact, I think
a future iteration on this may be to make it more generic so
it can act as an internal message bus where one of the messages
being published is "translationSyncReset".
2020-03-03 14:21:45 -06:00
Travis Turner
92eae8e715
Merge pull request #146 from travisturner/remove-errant-print
remove errant println from test
2020-03-03 12:39:28 -06:00
Travis
7aea54936e remove errant println from test 2020-03-03 11:27:36 -06:00
Travis Turner
13e7679fd9
Merge pull request #138 from travisturner/translate-partition-quick-fix
very crude fix for the translate key read-only bug
2020-02-29 16:18:50 -06:00
Travis
717bd09e97 include the test which covers this scenario 2020-02-29 08:43:10 -06:00
Travis
fb8f612afe very crude fix for the translate key read-only bug
This PR forces the non-coordinator nodes to reset their translation
sync (and therefore their own cosideration of read-only partitions)
any time they receive a `ClusterStatus` message. So basically, as the
cluster grows during the startup process, each node will reset their
translation sync.

This is NOT a good solution log term, but it should address the
immediate problem.

Things to note:
- the coordinator sync isn't getting reset, but that's ok, because the
immediate problem is a partition marked as read-only when it shouldn't
be; i.e. it's ok to have the inverse (a partition not marked as
read-only when it should be) because that partition won't receive
requests anyway.
- the last node to start is already correct and doesn't really need to
reset its sync.
- there are many other scenarios not covered by this fix.

Based on this theory:

```
i have another theory that i’m going to try to test.
this one would only apply in the case where a multi-node cluster is restarted with an existing, keyed index.
- start node0: it thinks it’s responsible for all partitions (nothing is read-only)
- start node1: it thinks it’s responsible for ~1/2 of the partitions and marks the other 1/2 as read-only
- start node2: it thinks it’s responsible for ~1/3 of the partitions and marks the other 2/3 as read-only
now if node0 is the coordinator receiving all translation requests, that still might not explain what’s happening, because in that case it would just do all the translating. i think. but either way, i should make sure that scenario is not happening, but i think it may be.

actually, that might explain it, because what would happen when the coordinator received a translation request, is that it would handle the 1/3 that it owned (now that the cluster is 3 nodes), and it would send the other 2/3 out to the other 2 nodes. but where it sent the requests wouldn’t line up with what the nodes thought they were responsible for based on the restart order
in this example, node 1 would receive requests for the wrong partitions
```
2020-02-29 08:43:05 -06:00
Matthew Jaffee
fcbebcf1b6
Merge pull request #103 from seebs/gencrash
don't mark a source as changed before we've finished remapping
2020-02-21 17:00:19 -06:00
Seebs
d742c67317
avoid race on max count reads and writes 2020-02-21 16:38:36 -06:00
Seebs
ba7db3028b
sanity-check: check whether containers are flagged as mapped before mapping
In the old unmarshal code, the decision to mark a thing as mapped (always
yes) happens separately from setting the mapping. What if this could ever
somehow possibly go wrong? Let's sanity-check that to be extra careful.
2020-02-21 16:38:35 -06:00
Seebs
7841a660a8
make sure setArray isn't copying mapped data addresses by accident in unionInPlace 2020-02-21 16:38:35 -06:00
Seebs
99d865c2ea
ensure that we've unrequested mapping when applying empty storage 2020-02-21 16:38:35 -06:00
Seebs
337e451cc7
lint and review changes
Log an error in the probably-irrelevant case where we ended up with
a file, but Stat failed, which shouldn't ever happen we hope anyway.

Also explicitly discard the status from RemapRoaringStorage in a case
where we don't care.
2020-02-21 16:38:35 -06:00
Seebs
cb686dcad0
make mmap test experiment with different amounts of mapping
This is sort of prototype-ish, but the idea is that we use SetMaxMapCount
from syswrap, which already exists, to let us test edge cases like
"what happens if you only sometimes have mapped data".
2020-02-21 16:38:35 -06:00
Seebs
63fb2f8539
generation testing and paranoia features
We might have a problem with a stale mmap, and to try to narrow it down
a bit, we add some sanity-checking features and panic recovery to the
generation Transaction code.

This is pretty experimental.
2020-02-21 16:38:35 -06:00
Seebs
372389fd30
don't corrupt files when mmap fails
In some cases, after a snapshot, if mmap fails, we could write
a duplicate of the bitmap to the file, creating cryptic "unknown
op type: 60" messages. This doesn't fix those files, but it stops
making them.
2020-02-21 16:38:35 -06:00
Seebs
f9e7fee47d
don't mark a source as changed before we've finished remapping
Also, check the remap operation for errors, and if an error occurs,
try to remap to nil (which shouldn't be able to fail).
2020-02-21 16:38:34 -06:00
Matthew Jaffee
ebab831a43
Merge pull request #113 from molecula/minMaxFloatHandling
min and max should properly scale their output for decimal fields
2020-02-21 16:38:11 -06:00
Matthew Jaffee
8c9b717b05
fix "worhtless" typo in comment 2020-02-21 16:00:31 -06:00
Matt Jaffee
fe46c84d19
also fix Sum query, but don't convert to float until the last step
this avoids compounding floating point errors while summing up the
numbers, and means less logic needs to change. Should probably convert
min and max to use this approach as well, though they don't suffer
from the compounding error issue, it is simpler.
2020-02-21 14:11:30 -06:00
Matt Jaffee
7321f9427c
min and max should properly scale their output for decimal fields
this involved adding an optional float value to the ValCount struct
which complicated result types, necessitated grpc changes, and needed
quite a few tests at different layers.
2020-02-21 14:11:29 -06:00
Matthew Jaffee
d369e3b4bf
Merge pull request #125 from travisturner/time-panic
send nil time value to prevent downstream panic
2020-02-21 14:08:53 -06:00
Travis Turner
52d450cbaf
Merge branch 'enterprise' into time-panic 2020-02-21 10:31:24 -06:00
Travis
13a1b3a2c1 send nil time value to prevent downstream panic 2020-02-18 15:55:40 -06:00
Kuba Podgórski
f3f11f4a44
Let translate keys as empty strings (#120) 2020-02-18 12:54:24 +01:00
Kuba Podgórski
57eb741c24
Don't allow an int and decimal fields to be created with keys=true (#118) 2020-02-14 08:47:31 +01:00
Kuba Podgórski
59f5d4f7d6
Do not clear existence column (#117) 2020-02-13 07:08:45 +01:00
Travis Turner
4713ccd0c8
Merge pull request #110 from travisturner/translatestore-fixes
WIP: Thread OpenTranslateStore through Holder to Index
2020-02-12 11:56:49 -06:00
Ben Johnson
c8cefea897
Fix test performance 2020-02-12 10:25:26 -06:00
Travis
d9ef4c0986
use OpenInMemTranslateStore by default in tests 2020-02-12 10:25:25 -06:00
Travis
4dd530e956
open bolt translate store partitions asynchronously 2020-02-12 10:25:25 -06:00
Travis
49c8bf01a0
WIP: Thread OpenTranslateStore through Holder to Index 2020-02-12 10:25:25 -06:00
Cody Soyland
f9f6fce6b4
Merge pull request #111 from codysoyland/go-1.14-rc
Add Go 1.14-rc to CI
2020-02-10 07:59:48 -06:00
Cody Soyland
88c3477010 Add Go 1.14-rc to CI 2020-02-06 19:46:01 -06:00
Kuba Podgórski
e77c69d212
Update handler.go (#108) 2020-02-05 22:14:25 +01:00
tgruben
fc6fd150ba
Merge pull request #106 from tgruben/bug-105
handle missing index in join properly
2020-02-05 10:29:56 -06:00
Todd Gruben
0acac34fee travis suggetions 2020-02-04 15:21:55 -06:00
Todd Gruben
3140b2d8cb handle missing index in join properly 2020-02-04 11:55:49 -06:00
Kuba Podgórski
3bb45ea2c0
Fix Set operation for float numbers on decimal fields. (#101) 2020-02-03 19:29:15 +01:00
Kuba Podgórski
7c395ac4d1
Simplify Holder's logic for CreateIndex (#104) 2020-02-03 17:41:06 +01:00
Travis Turner
b693688677
Merge pull request #60 from molecula/translation-sharding
Translation sharding
2020-01-31 10:44:51 -06:00
Travis
9b4c7610e6 Merge branch 'enterprise' into translation-sharding 2020-01-31 10:13:44 -06:00
tgruben
eca14d8608
Merge pull request #97 from tgruben/row-difference-in-place
Difference in place at row level
2020-01-30 15:10:23 -06:00
Travis Turner
8626a2a710
Merge pull request #99 from travisturner/translation-sharding
Ensure ForeignIndex key translation happens in API.
2020-01-30 14:42:41 -06:00
tgruben
1be22f13e8
Merge pull request #2 from travisturner/row-difference-in-place
fix differenceInPlace test
2020-01-30 14:31:30 -06:00
Todd Gruben
f498a40d97 go mod tidy 2020-01-30 14:28:44 -06:00
Travis
0bdcb5ab0a fix differenceInPlace test 2020-01-30 13:38:31 -06:00
Travis
61e527251a fix some comments 2020-01-30 10:56:03 -06:00
Todd Gruben
8de32fd62a high level support for difference in place 2020-01-30 08:11:43 -06:00
Travis
e40400b130 Ensure ForeignIndex key translation happens in API.
For Fields with ForeignIndex (which have keys), the API was missing
the logic to do that translation against the translateStore of
the foreign index. This commit adds that logic, as well as some
missing translateStore-related logic in the gRPC code.
2020-01-28 22:46:12 -06:00
tgruben
32b92abd6e
Merge pull request #94 from tgruben/diff-inplace
Adding roaring in place difference support
2020-01-23 08:23:47 -06:00
tgruben
014c3a98a5
Merge pull request #1 from travisturner/diffinplace
tidy comments and remove pilosa dependency
2020-01-22 12:09:50 -06:00
Travis
bb80d1ed2d tidy comments and remove pilosa dependency 2020-01-22 11:59:32 -06:00
Todd Gruben
f40ced47fa included previous patterns for in place testing 2020-01-21 16:56:33 -06:00
Travis Turner
43b8d7827a
Merge pull request #90 from travisturner/translation-sharding
Field.ForeignIndex translation on ImportValue()
2020-01-17 17:25:14 -06:00
Travis
d41ee99052 linter fix 2020-01-17 14:46:43 -06:00
Travis
b620e37e51 move the foreign index key check into applyTranslateStore() 2020-01-17 14:41:41 -06:00
Travis
f001ad199f use translateIndexKeys instead of translateIndexKeySet in ImportValue() 2020-01-17 11:58:15 -06:00
Travis
efffa39c2c check foreign index on field open 2020-01-17 11:42:21 -06:00
Travis
90a2e116a7 update translateResult to translate foreign index keys on SignedRow results 2020-01-17 11:10:42 -06:00
Travis
0ba5b48fca Field.ForeignIndex translation on ImportValue() 2020-01-16 22:23:29 -06:00
Ben Johnson
10ccb6d523 translate foreign index 2020-01-16 13:53:12 -06:00
Ben Johnson
4020f8c73e fix cross-index translation 2020-01-15 14:28:06 -06:00
Travis
54679c12c4 post merge, needs review of TODOs 2020-01-14 22:10:12 -06:00
Travis
df51f07f96 Merge branch 'enterprise' into translation-sharding 2020-01-14 20:05:12 -06:00
Travis Turner
0459285101
Merge pull request #87 from travisturner/grpc-connection-reset
reset grpc connection after TransientFailure
2020-01-14 16:26:02 -06:00
Travis
757df0d284 reset grpc connection after TransientFailure 2020-01-14 15:18:25 -06:00
Travis
f232ec4277 Merge remote-tracking branch 'upstream/enterprise' into enterprise 2020-01-14 15:18:09 -06:00
Matthew Jaffee
12c6cd1c4e
Merge pull request #88 from jaffee/grpc-mutex-string-bug
mutex field data type should be string not []string
2020-01-12 18:27:47 -06:00
Matt Jaffee
ff9ad9a4fe
mutex field data type should be string not []string 2020-01-12 17:38:43 -06:00
tgruben
ba70bf3079
Merge pull request #89 from tgruben/bug-q2-double-delete
bit remove leaves internals corrupt on empty edge case
2020-01-12 16:25:31 -06:00
tgruben
3261ec4dc4
Merge branch 'enterprise' into bug-q2-double-delete 2020-01-12 16:09:12 -06:00
Todd Gruben
99108a1c63 bit remove leaves internals corrupt on empty edge case 2020-01-12 12:00:00 -06:00
Travis
89f6429dac Merge remote-tracking branch 'upstream/enterprise' into enterprise 2020-01-10 15:45:25 -06:00
Travis Turner
9015c00da9
Merge pull request #84 from travisturner/foreign-index
Add FieldOption.ForeignIndex
2020-01-10 15:45:02 -06:00
Travis
a6a2f84bd5 During Holder.Open, apply foreign index after all indexes open
In the case where a field with a foreign index opens before the
foreign index has opened (and is available as a reference in the
holder), push the field into a queue to have its foreign index
applied once all indexes have opened.
2020-01-10 12:28:28 -06:00
Travis
3d3286a9ca fix an issue caused by empty column list defaulting to IDs 2020-01-10 12:28:28 -06:00
Travis
f79fde43e3 exclude internal fields (i.e. _exists) from Inspect output 2020-01-10 12:28:28 -06:00
Travis
742135dc10 Get ForeignIndex string value when reading BSI field.
In the `Inspect` function in `server/grpc.go`, getting
the value of an `int` field with a foreign index to
an index with `Keys()`, we need to return the string
key value instead of the BSI int value for the field.

This commit also changes the method `Field.keys()` to be
exported as `Field.Keys()` so that it's accessible in
the server package.
2020-01-10 12:28:28 -06:00
Travis
35f9dfa374 remove write portion of extension data race 2020-01-10 12:28:28 -06:00
Travis
881d3bef06 Adjust the FieldOption logic to be in place prior to field.Open().
This commit changes the order of FieldOption application so that
it's always set before field.Open() is called.

This was required because field.Open() now uses some of the values
from FieldOptions to determine if/when to use a particular
translateStore. For example, when FieldOptions.ForeignIndex is set,
the translateStore from the foreign index is retrieved during
field.Open().
2020-01-10 12:28:28 -06:00
Matt Jaffee
4d8f307c5e handle string values in ImportValueRequest sorting 2020-01-10 12:28:28 -06:00
Matt Jaffee
132cf7cc1c add StringValues to proto ImportValueRequest, update proto versions
I ran:

brew upgrade protobuf
GO111MODULE=off go get -u github.com/gogo/protobuf/protoc-gen-gofast

I'm not sure if everything is still going to work, but I'm excited to
find out!
2020-01-10 12:28:27 -06:00
Travis
b22d0143e4 loadNewExtensions is unused, but included for completeness 2020-01-10 12:28:27 -06:00
Travis
1542cbefc0 Add FieldOption.ForeignIndex
This allows a BSI field to have an option indicating
that it is a foreign key to another index. If the foreign
index has column keys, then this field handles string values
by using the foreign index's translate store.
2020-01-10 12:28:27 -06:00
Travis
5ca37bf3f3 reset grpc connection after TransientFailure 2020-01-10 11:49:33 -06:00
Matthew Jaffee
7aef0743e1
Merge pull request #86 from jaffee/field-char-limit
allow field and index names up to 230 characters
2020-01-09 14:43:55 -06:00
Matt Jaffee
0a1de81441
allow field and index names up to 230 characters
The lowest limitation I've seen on any filesystem we care about is 255
characters. 230 leaves enough space that an index or field could be
backed up and have a timestamp and file extension appended while
still allowing for much longer index and field names.
2020-01-09 13:02:22 -06:00
Ben Johnson
cda2729935 fix bitdepth race 2020-01-08 09:47:43 -07:00
Ben Johnson
1f6910b0b8 fix group by test 2020-01-08 09:47:43 -07:00
Ben Johnson
a043490996 add multi-shard translation 2020-01-08 09:47:43 -07:00
Ben Johnson
bdfdeb1291 fix lint 2020-01-08 09:47:43 -07:00
Ben Johnson
a189477ba3 rebase & fix test const 2020-01-08 09:47:43 -07:00
Ben Johnson
1409ab5664 fix data race 2020-01-08 09:47:43 -07:00
Ben Johnson
1b068f75a8 Fix inmem read only translation bug 2020-01-08 09:47:43 -07:00
Ben Johnson
2f76283f03 fix replication errors & test races 2020-01-08 09:47:43 -07:00
Ben Johnson
9647d9b4bb fixing additional tests 2020-01-08 09:47:43 -07:00
Ben Johnson
c0a129979e fix tests 2020-01-08 09:47:43 -07:00
Ben Johnson
e3606d6615 fix id generation 2020-01-08 09:47:43 -07:00
Ben Johnson
82910911dd refactoring id partitioning 2020-01-08 09:47:43 -07:00
Ben Johnson
f31d68739e holder syncer translate implementation 2020-01-08 09:47:43 -07:00
Ben Johnson
b3e86e8394 refactoring stores back into index/field 2020-01-08 09:47:43 -07:00
Ben Johnson
7215bfd16c Implement translator store sharding 2020-01-08 09:47:43 -07:00
Travis Turner
cabfa3c456 add a test for pilosa/#2084 2020-01-08 09:47:43 -07:00
tgruben
457789effd
Merge pull request #62 from tgruben/clearvalue
add support to clear value for column
2020-01-07 13:12:21 -06:00
Todd Gruben
643884aeb3 refactored clear to fix q2;removed unused comment 2020-01-07 12:55:32 -06:00
Todd Gruben
26e3460413 removed view creation from ClearValue 2020-01-07 10:55:45 -06:00
Todd Gruben
d843959904 fixed comments; removed create fragment 2020-01-07 10:39:56 -06:00
Todd Gruben
75e017cf4f Merge remote-tracking branch 'upstream/enterprise' into clearvalue 2020-01-07 10:28:47 -06:00
Cody Soyland
29f7448b89
Merge pull request #83 from codysoyland/expvar-compatibility
Initialize expvar lazily to prevent panic if importing both Pilosa v1 and v2
2020-01-02 17:56:42 -06:00
Cody Soyland
8d32005ede Initialize expvar lazily to prevent panic if importing both Pilosa v1 and v2. 2020-01-02 15:43:34 -06:00
Travis Turner
5643afac47
Merge pull request #82 from travisturner/row-response-sorter
WIP: RowResponseSorter for sorting a list of RowResponse based on sort params
2019-12-31 13:18:05 -06:00
Travis
0fffd9a0cb RowResponseSorter for sorting a list of RowResponse based on sort paraters 2019-12-31 11:52:01 -06:00
Travis Turner
c247805d96
Merge pull request #81 from travisturner/inspect-field-output
Remove empty field check in Inspect()
2019-12-27 13:42:36 -06:00
Travis Turner
98df5672e9
Merge branch 'enterprise' into inspect-field-output 2019-12-27 13:26:38 -06:00
Travis Turner
768de9dc3a
Merge pull request #80 from travisturner/row-response-error
Add StatusError to RowResponse for better error handling.
2019-12-27 13:25:38 -06:00
Travis
3be4141382 Return the correct data type label in grpc header
Based on the pilosa field type, return the correct data type
label in the gRPC column header.
2019-12-27 12:43:45 -06:00
Travis
73090e05c8 Add StatusError to RowResponse for better error handling.
This PR adds a `StatusError` to the `pproto.RowResponse` type, which
allows a stream to pass an error on the stream (encoded into
the `RowResponse.StatusError`). This can be checked downstream
for matching `EOF` or `err != nil` and handled appropriately.

This is helpful mainly with the `RowResponse` reducers which run in
goroutines. Instead of trying to manage a separate channel of errors
from those goroutines, we just follow the grpc model and send the
error with the stream.
2019-12-27 12:43:45 -06:00
Travis Turner
94f97297eb
Merge pull request #77 from travisturner/all-shard
Allow All() to be called at the shard level
2019-12-27 12:35:41 -06:00
Travis
d34e38f134 Remove empty field check in Inspect()
The check for field existence is not necessary; since we
add the `_id` field to every response then at the very
least that field will be returned.

This check was preventin a query like `select _id from ...`
from returning any results.
2019-12-26 22:27:46 -06:00
Travis
586a13e942 Allow All() to be called at the shard level 2019-12-20 22:44:46 -06:00
Cody Soyland
7b30b91448
Merge pull request #74 from codysoyland/docker-build-vendor
Vendor modules before building docker image so private modules can be downloaded
2019-12-20 17:52:26 -06:00
Cody Soyland
d4117f3137 Vendor modules before building docker image so private modules can be downloaded 2019-12-20 16:05:18 -06:00
seebs
47316d9f2f
Merge pull request #70 from seebs/unionAA
Simplify unionArrayArray
2019-12-20 13:49:51 -06:00
seebs
d4d3d75e28
Merge branch 'enterprise' into unionAA 2019-12-20 13:28:57 -06:00
Matthew Jaffee
d86a3c3f2f
Merge pull request #55 from seebs/pluginfix
Pluginfix
2019-12-20 12:53:09 -06:00
Matt Jaffee
fe0f57651e
build with distinct by default 2019-12-20 12:21:47 -06:00
Cody Soyland
49b2029656
Run "go mod vendor" outside of Docker so authenticated modules may use system credentials 2019-12-20 12:21:47 -06:00
Seebs
7e1fd8392f
go.mod/go.sum changes for using molecula/ext
This pins us to the initial external release of molecula/ext, which
with any luck will be the only one. (Narrator: It was not to be the
only one.) We also use GOPRIVATE so we don't need a replace directive.
2019-12-20 12:21:47 -06:00
Seebs
0eba050054
stop using pkg/plugin, start using build tags
After a few experiments with pkg/plugin, I'm ready to concede that the
people warning me it was unsuitable for production use were in fact
correct.

In the brave new world, the "ext" package is moved to its own module
outside pilosa. This means that importing it doesn't imply any need to
version-check against pilosa; we can just use versioned copies of the
ext package, which can be public because it doesn't contain anything
we need to care about keeping proprietary.

Then we can, conditional on build tags, import modules from a
neighboring repo which contains the actual implementations, and if
they're imported, their init functions register them.
2019-12-20 12:21:47 -06:00
Seebs
f51c2dbc42
use extensions through build tags 2019-12-20 12:21:47 -06:00
Travis Turner
179fb910f7
Merge pull request #71 from travisturner/all-limit-offset
Add All() support to PQL, including limit and offset
2019-12-18 22:10:42 -06:00
Travis
361e51cb41 Add All() support to PQL, including limit and offset
This PR is meant to get all columns from an index
based on the TrackExistence row.

`All()` is a PQL function that can be used as a typical
row object. Optional arguments are `limit` and `offset`.
2019-12-18 18:00:15 -06:00
Seebs
83aa505673 Simplify unionArrayArray
Also short-circuit it in some cases.
2019-12-17 15:30:56 -06:00
Travis Turner
1af016df84
Merge pull request #68 from travisturner/linter-fix
Fix an impossible code path raised by the linter
2019-12-17 09:04:37 -06:00
Travis
532caa0fbf fix an impossible code path raised by the linter 2019-12-16 21:56:57 -06:00
Travis Turner
6f556fb880
Merge pull request #63 from travisturner/row-field-label
Wrap return types: RowIdentifiers, Pair, and []Pair
2019-12-16 07:42:20 -06:00
Travis
4f7f4f58b1 add field to SignedRow, and implement its grpc response 2019-12-14 15:56:06 -06:00
Travis
3b7b54094a update clustertests to use v2 (and go 1.13) 2019-12-13 18:45:43 -06:00
Travis
5cb37834a0 Wrap return types: RowIdentifiers, Pair, and []Pair
This PR adds a field name (string) to the return types
which represent the values from a specific field. For example,
a TopN query on field `x` would be `TopN(x)` and have results
like:
```
[]Pair{
  {ID: 14, Count: 10},
  {ID: 3, Count: 8},
  {ID: 7, Count: 3},
}
```
In order to know what field this result type refers to, we wrap
`[]Pair` in a new struct called `PairsField` which contains an
addition `Field` string where `x` is stored.

This is useful for informing the gRPC server how to construct
more appropriate headers for the result stream (in this case,
the column headers can now be "x" and "count").

Similar logic was applied to `RowIdentifiers` and `Pair` as well.
2019-12-13 15:36:51 -06:00
Travis Turner
c5aeed0715
Merge pull request #57 from tgruben/fix-minmax-count
return total match counts for either min or max
2019-12-13 15:28:27 -06:00
Todd Gruben
4523a4d693
removed uneeded test run 2019-12-13 15:10:28 -06:00
Todd Gruben
16171b3e65
return total match counts for either min or max 2019-12-13 15:10:28 -06:00
Todd Gruben
95f2864abe applied suggestions by @travisturner 2019-12-11 12:13:57 -06:00
Todd Gruben
7a2d90ade8 add support to clear value for column 2019-12-09 16:28:03 -06:00
Travis Turner
c4e339f72b
Merge pull request #59 from travisturner/not-found-code
Add grpc NotFound code where applicable
2019-12-03 17:44:30 -06:00
Travis
a5652a182c add grpc NotFound code where applicable 2019-12-03 11:53:20 -06:00
Matthew Jaffee
521ea603d0
Merge pull request #52 from molecula/import-col-attrs
Import col attrs
2019-12-02 01:25:08 -06:00
Matt Jaffee
87ee83f4cb
check errors in test to fix lint 2019-12-01 07:33:25 -06:00
Matt Jaffee
9e3029b969
re run generate-protoc 2019-12-01 07:33:24 -06:00
Alan Bernstein
e470b3276e
Add generated proto 2019-12-01 07:33:24 -06:00
Alan Bernstein
cf7d668b49
Support import column attrs in client 2019-12-01 07:33:24 -06:00
Alan Bernstein
c3e8284f6c
Test for presence of column attrs 2019-12-01 07:33:24 -06:00
Alan Bernstein
628def3db7
Clarify some error messages 2019-12-01 07:33:24 -06:00
Alan Bernstein
aba67364b1
Add support for importing column attrs 2019-12-01 07:33:23 -06:00
Travis Turner
76bb3985f0
Merge pull request #53 from travisturner/having-between
Add support for BETWEEN type conditions in the having clause.
2019-11-30 21:58:45 -06:00
Travis
52debbc389 Add support for BETWEEN type conditions in the having clause.
There is a TODO in the `StringWithSubj` method because the value
types really depend on the subject type (for example, `count` uses
uint64, while `sum` uses int64). I'm waiting to address this
until we decide how to handle sums of floats (Decimal), because
that will affect this logic as well.
2019-11-30 11:59:09 -06:00
Travis Turner
0247a9073c
Merge pull request #51 from travisturner/groupby-having
Add "having" support to GroupBy() queries
2019-11-29 23:01:15 -06:00
Travis
24d02c1920 Add "having" support to GroupBy() queries
This PR adds support for a `having` argument in a `GroupBy` query.
Usage looks like this:
```
GroupBy(Rows(a), having=Condition(count > 10))
GroupBy(Rows(a), aggregate=Sum(field=b), having=Condition(sum > 100))
```
2019-11-28 18:40:57 -06:00
Travis Turner
bc0018b67b
Merge pull request #50 from travisturner/datatype-fixes
Add StreamClient and StreamServer interfaces
2019-11-27 17:21:55 -06:00
Travis
3bc0dc28f0 Add StreamClient and StreamServer interfaces
In order to standardize results as streams of RowResponse,
this PR introduces two interfaces `StreamClient` and
`StreamServer`) which mirror the grpc stream interfaces.
Upstream users (sqlmapper, vdsm, etc) can implement
instances of these interfaces to ensure that results can
stream through the entire sytem in an expected way.

This PR also fixes a couple of missing data types.
2019-11-27 16:10:46 -06:00
Matthew Jaffee
210676c927
Merge pull request #39 from molecula/groupby-sum
Groupby sum
2019-11-27 16:04:42 -06:00
Matt Jaffee
114c1a9df8
remove unecessary span from executor tracing 2019-11-27 11:09:06 -06:00
Matt Jaffee
60397d3e8f
add more tracing around groupBy 2019-11-27 11:00:13 -06:00
Matt Jaffee
f2f9ea01dc
get group by aggregates working with PQL validation and grpc streaming 2019-11-27 11:00:13 -06:00
Ben Johnson
ea9914dba0
Add optional GroupBy() 'aggregate' field.
This commit adds an `aggregate` field that allows a `Sum()` call
to be executed for every returned group.
2019-11-27 11:00:13 -06:00
Matt Jaffee
81a4d32cdd
allow IDs to be passed even when keys enabled
This change allows one to query Pilosa fields and indexes directly
with integer row and column ids even when key translation is
enabled. This was previously disallowed during query
translation... I'm not sure why, but it can be quite useful for
debugging and testing to be able to use IDs directly. I have a test in
go-pilosa which uses this functionality.

I also simplified a bunch of the test code which was of the form:
```
else {
    if blah {
    }
}
```

to be:

```
else if blah {
```

which I think is pretty harmless.

I also changed a snapshot log line that has been bugging me to be
Debug level so that it isn't generating lots of useless logs for long
running Pilosa instances.
2019-11-27 08:41:40 -06:00
tgruben
16d5db97a6
Merge pull request #47 from tgruben/inspect-fix
fixed bug in slice container seek
2019-11-26 11:35:51 -06:00
Todd Gruben
ca0247e35b fixed bug in slice container seek 2019-11-26 09:21:52 -06:00
seebs
407c309640
Merge pull request #46 from seebs/distinctfix
Distinctfix
2019-11-22 17:29:24 -06:00
Seebs
d79ecbad86 recompute shards for cross-index calls
It turns out that we need to recompute the set of shards whenever
a query is cross-index. Otherwise we get partial results in unexpected
ways sometimes.
2019-11-22 16:02:47 -06:00
Seebs
36ef82d7ac Zero bitmap storage when reusing it for container-as-bitmap
If you don't do this, it works fine the first time you use a given
storage, but after that you start seeing spurious bits.
2019-11-22 16:02:42 -06:00
Seebs
397d93e84b provide an empty filter when a filter was empty 2019-11-22 16:02:31 -06:00
Seebs
26326ac74c recompute shards for cross-index queries
When computing results on another index, recompute list of
shards for that index.
2019-11-22 16:02:26 -06:00
Seebs
6ad39a376e handle precalls and cross-index queries better
There's two actual changes here, but they're closely related.

First, handle named parameters for precalls, not just indexed parameters.
Second, when doing translation for a call, check whether it specifies an
index, and if it does, use that index instead of the current index for
the translation.
2019-11-22 16:02:20 -06:00
seebs
16c3cfa727
Merge pull request #42 from seebs/sqdeadlock
use the right lock for Enqueue
2019-11-18 21:53:00 -06:00
seebs
01309e4fc5
Merge branch 'enterprise' into sqdeadlock 2019-11-18 20:51:40 -06:00
Cody Soyland
d3c8728821
Merge pull request #19 from codysoyland/ci-updates
Update CI to support Pilosa Enterprise (private dependencies)
2019-11-18 13:52:20 -06:00
Cody Soyland
58182ff563 Pilosa Enterprise private CI 2019-11-18 13:30:32 -06:00
Travis Turner
295adbfe67
Merge pull request #44 from travisturner/cache-threshold-deletes
Fixed ranked cache logic to support reducing cached values below the threshold
2019-11-18 12:10:46 -06:00
Travis
ed82a535e5 Fix ranked cache logic to support reducing cached values below
the threshold.

Prior to this commit, if a cache value was reduced to a value
that fell below the threshold, the operation would be ignored
and the cached value would remain at the old, higher value.

This commit also fixes logic which reduces a cached value within
the framework of uint64 values by subracting the absolute value
of the negative value (since adding a negitive doesn't work with
unsigned integers).
2019-11-18 11:39:50 -06:00
Travis Turner
32f754899e
Merge pull request #43 from travisturner/translate-race-in-test
allow for translate store race in test
2019-11-15 16:33:30 -06:00
Travis
0a69fca657 allow for translate store race in test (by using retry)
In this case, the test is reading from the translateStore
replica before the translateStore replication has had time to
deliver its log to the replica. The only way to truly address
this in the translate store would be to route all key misses
that happen on a read-only replica to the primary translate
store (or somehow know when the primary is done sending to
replicas) for actual verification that the key does not exist.
That's more involved than we want to do here; this PR just
addresses the problem in the test.
2019-11-15 07:57:47 -06:00
Seebs
f204b37760 use atomics instead of locking for stats 2019-11-14 17:40:14 -06:00
Seebs
bab077199c use the right lock for Enqueue
The request for a non-read lock blocks until all existing read
locks exit, meaning that if an Immediate operation is already
going for a fragment, an Enqueue operation will hang forever
holding the fragment's lock, while the Immediate operation has
probably relinquished the fragment's lock to wait for the
queue worker to process it. But the queue worker can't process
it, because the incoming Enqueue still holds the fragment's
lock. Solution: Don't block the Enqueue operation like that.
It shouldn't coexist with things that actually change the sq
channels, like Stop(), but it is fine for it to coexist with
other queue operations.
2019-11-14 17:00:34 -06:00
seebs
9cec40e69d
Merge pull request #41 from seebs/roaringProto
Stop using Roaring in protobuf messages until it's supported elsewhere
2019-11-14 12:45:35 -06:00
Seebs
6fc6cc4350 Stop using Roaring in protobuf messages until it's supported elsewhere
go-pilosa uses protobuf to talk to us but doesn't support the roaring
format. Conveniently, there's a kill switch.
2019-11-14 10:54:40 -06:00
Matthew Jaffee
fa9c911860
Merge pull request #37 from travisturner/rename-bool-label
Rename bool label from changed to result
2019-11-13 14:30:14 -06:00
Travis
e8cd48155a
Rename bool lable from changed to result 2019-11-13 14:12:52 -06:00
Matthew Jaffee
4dfeb89b43
Merge pull request #36 from travisturner/includescolumn-keys
Add column keys support to IncludeColumn
2019-11-13 14:09:24 -06:00
Travis
625125bac6 add column keys support to IncludeColumn 2019-11-13 11:34:21 -06:00
Matthew Jaffee
013ee21621
Merge pull request #28 from molecula/pql-float-values
Pql float values
2019-11-13 11:04:36 -06:00
Matt Jaffee
0e445db7ff
improve error message checking field type in import roaring 2019-11-13 10:07:24 -06:00
Travis
26fc621f09
Support integer predicates in Decimal field range queries. 2019-11-13 10:07:24 -06:00
Matt Jaffee
0ac778516e
check error, make linter happy 2019-11-13 10:07:24 -06:00
Matt Jaffee
14dfc9e31d
fix comment typo for BTWN_LTE_LT 2019-11-13 10:07:24 -06:00
Matt Jaffee
9c8ad727b5
allow floats in PQL queries for decimal fields
had to workaround some cruft in the parser that was trying to only
support a BETWEEN query as LTE, LTE. Now we have operations for all
combinations of LT and LTE.

unrelated - changed the port a test was binding to as it conflicted
with a port I was using locally.
2019-11-13 10:07:24 -06:00
Matt Jaffee
0fec16a141
fix integer bug on less than queries.
this was introduced recently to fix another bug. the comment above it
is correct, just the logic was off-by-one. The test shows the issue
and was confirmed to reproduce it and then fix it.
2019-11-13 10:07:23 -06:00
Travis Turner
7401fd1333
Merge pull request #33 from travisturner/grpc-logger
Fixed gRPC server logger; pass logger through from main
2019-11-13 09:56:04 -06:00
Travis Turner
afd1c004f9
Merge branch 'enterprise' into grpc-logger 2019-11-13 08:31:26 -06:00
Travis Turner
d3432478f9
Merge pull request #34 from travisturner/bool-returns
Fix makeRows in gRPC hander to handle a bool result
2019-11-13 08:24:43 -06:00
Travis
7fd5248d98 makeRows in gRPC hander now handles a bool result
This PR adds bool support to the makeRows function
in the gRPC handler.
2019-11-12 16:13:52 -06:00
seebs
1fea1ea375
Merge pull request #22 from seebs/fsckSnapshotExtension
This is a collection of changes that have been pending forever. It improves the snapshot queue performance, adds some amount of recovery for corrupt filles, reduces memory usage in the rowcache, and adds an extension interface. Yes, they should probably have happened separately over time, things happened.
2019-11-12 14:50:34 -06:00
Seebs
1e0873c70b lock BufferLogger for reads/writes
With the new addition of the holder background scan, it's possible
for an open holder to write log messages at arbitrary times. The
TestHolder_Open/ErrIndexName test checks the contents of the output
buffer, but those contents could be changing if the background task
happens to run at the right time. Use trivial locking around that
so that this shouldn't happen.
2019-11-12 12:15:13 -06:00
Seebs
03f3f424aa don't lint PEG files
I was pretty sure I'd done this, but I guess not: Skip linting
the PEG files.
2019-11-12 12:15:13 -06:00
Seebs
8cc7a176b5 license header fixups
Fix up license headers for the extension code, and add the proto
file to the list of things we don't check license headers for.
2019-11-12 12:15:13 -06:00
Seebs
c5136b14db ensmarten snapshot queue
The snapshot queue needs a bit more subtlety. In some cases,
we really do want to do a snapshot right now -- these shouldn't
have to wait for possibly a hundred or more other snapshots
to complete.

In other cases, we don't really care that much whether we do
a snapshot, and just dropping it is probably fine.

To accommodate this, we distinguish between "urgent" and
"normal" snapshots, and between "Immediate" (does an urgent
snapshot, waits for it) and "Enqueue" (might enqueue a snapshot
but *also might not* if we're already busy). There's a
corresponding "Await" to wait for a snapshot, if one is
pending, but not if one isn't.

We also have a background scan that checks the holder. It will
scan pretty actively when it's finding fragments that need
snapshots (no enqueued snapshot, opN > MaxOpN). It pauses
for a second after every hundred fragments that didn't need
snapshots, and for a minute after each holder scan that didn't
find any. So, if you don't need snapshots, it does basically
nothing, if you do, it'll be moderately aggressive about
submitting tasks -- but it always waits if there's *any*
requested snapshots in the queues.

Updates since initial draft:

Check results from Await more consistently, and in one case, use Immediate
instead and then check its error.

Fix a race condition.  The race condition comes about if:

1. You have a limited enough worker pool that this can happen.
(In testing we tend to have a worker pool of 1.)
2. A fragment is in the normal, non-urgent, queue already.
3. An immediate request comes in for that fragment. This always
happens *with the fragment lock held*.
4. A worker thread grabs that fragment from the queue.
5. The worker thread now waits on the lock. Meanwhile, the
immediate request blocks on sending the fragment to the urgent
queue.
6. The worker can't read the urgent queue, and the immediate
request can't send it, so the immediate request can't proceed.

What's supposed to happen is that the immediate request sends
the thing, and gets into Await(), which sleeps on a condition
variable using the lock, which is to say, releases the lock.

The obvious resolution is to let go of the lock, send the
message, and then reclaim the lock. But then we have the
possibility that the message sent ends up with a timestamp
right after a snapshot that happened *after* the Immediate
request was started. Oops. So we create the request, then let
go of the lock, then send the request, then reclaim the lock
and go into the Await state. All is well.

This is on top of more general use of wait groups, etcetera,
to allow us to ensure that any holder scans terminate *before*
we close the channels they might otherwise be trying to write to.
So, shutdown process is now:

* grab lock on queue (workers and scanners don't use the lock)
* mark snapshotqueue done
* wait for holder scans to complete/exit
* close and nil out all the channels
* release lock

Anything trying to submit to this needs to hold the lock, unless
it's a holder scan, so either it got the lock before we did and already
submitted the thing, or it will get the lock after this and not find
a channel to write to; it's just the holder scanner that has an
ongoing thing that might have started a write to the channel *without*
a lock held, because it's expected that it might have to wait minutes
or hours before the write will complete because it's a background task.

Also, rework the background holder scan to grab lists of
indexes/fields/views/fragments, then scan the grabbed/copied lists,
rather than iterating over maps, allowing us to grab the lock when
we're about to access a thing and let it go when done.

There might be a simpler/cleaner way to do this but opinions on how
safe it is are very mixed, so in the mean time, I'm making the range
behavior not depend at all on there being no writes to the various tiers
of holder/index/view/fragment during the background scans.
2019-11-12 12:15:13 -06:00
Seebs
3b696da34a plugins and precomputed data
So in some cases, when we do a query, the results of one
part of the query are innately shared-across-nodes; for
instance, a hypothetical Distinct query. More generally,
we allow cross-index queries; calls can have "index=foo"
in them.

This patch lets us handle that without duplicating that
query all over. Before we actually start doing the
separate calls, we run the query once from the coordinating
node, then patch the results in, and send relevant subsets
over to each client, etcetera. Also provides slightly
friendlier (and I hope faster) support for converting
bitmaps to/from sets of rows.

We also add an extension interface, and some fancy stuff
to let us define new calls, which use this. They're sort
of tied together because the first extension I wanted to
implement needed precomputed calls. The extension API
lets us create extensions using `pkg/plugin` (with all its
associated limitations, unfortunately), then query them
at load time for functionality.

This also implies some revamping of the argument
validation for PQL, like verifying that functions exist
and knowing things about their argument types.

So basically this is an overly intrusive patch, and would
be better as separate patches, but they're hard to detangle.

add trivial execution-time profiling

What if you could ?profile=true on a query and get some
numbers back? That'd be really cool.

We already have tracing/spans, but right now, those only generate
any data if you have something set up for them to trace to. Add a
fancy wrapper that lets us generate our own tracing data, and dump
it into the request response, if ?profile=true.

add a sample extension, add missing features to extension interface

Implement a naive probabilistic filter extension as an example of
what an extension looks like. In the process, discover multiple
omissions in the bitmap API. Well, I did *say* it was experimental.
2019-11-12 12:14:29 -06:00
Seebs
b25eb8f596 Sources and Generations: tracking mmapped files
This code represents an attempt at providing reliable tracking
of whether any bitmaps still in use have access to a given block
of mmapped data, allowing us to unmap the data when nothing is using
it anymore.

The basic approach is as follows: Each mmap is associated with
a new object, called a "generation". A generation reflects
a particular instance of a given file being mapped. When a
bitmap is built from an mmapped data source, the bitmap is
given a pointer to the generation as its Source. When bitmap
operations combine containers from other bitmaps, they
produce new bitmaps that are tagged with the combined set of
sources.

When we snapshot a file, or for some other reason wish to remap
it, the corresponding bitmap has all its containers updated to
use the new storage, and the bitmap's source is changed. However,
previously-handed-out containers might still have references to the
old storage. Those containers would be in bitmaps with the old
source.

After a bunch of study of trying to reference-count and track
this, I realized: We don't actually need to do that, because we
already have something suitable for determining whether anything
can reach a given object. It's the garbage collector.

So we set a finalizer on the generation object, which handles
unmapping. There's additional sanity-checks here to confirm things
like "we thought this generation should be expiring", and we
track timestamps. We could also have things check whether a
given bitmap's source was marked as obsolete "a while ago", but
that isn't implemented yet.

There's a debug version of this which tracks finalization, creation,
and ending timestamps, and has a call to provide diagnostics for
this. Identical generation IDs get separated out with random
suffixes in this case -- there's sometimes a second or third
instance of the same name due to a holder closing and reopening,
but this basically only happens in testing.

Note that generations are still used even when there's no mmapping,
but unless debugging is turned on, they shouldn't propagate much --
we don't consider a generation to be the source of a bitmap unless
the bitmap actually mapped things from that generation's mmapped
storage, or debugging is on.

There's a couple of other, possibly more subtle, changes and
bug fixes that got caught by the testing on this:
* If a fragment is partially opened and then opening some later
  part fails, we close the earlier parts before returning the
  error so we aren't leaving it partially open.
* Several operations on segments which were requesting that a
  frozen copy of a bitmap be created are now actually *replacing*
  their bitmap with the frozen bitmap, rather than discarding it.
* intersectRunRun, if it decides to create an array or bitmap,
  will yield that container instead of discarding it.

And why all of this? Why, so we can actually implement the thing
where when a fragment has a valid roaring bitmap, but the ops log
is corrupt, we can truncate the corrupt part of the ops log and
reopen it. Which I did.

When the generationdebug build tag is in use, every generation
has a finalizer all the time. When it's not, they only get finalizers
when we expect them to be done -- say, when closing a fragment.
This is because finalizers appear to be possibly-expensive.

There's some logical cleanup to openStorage here, dividing part
of its work into applyStorage and importStorage, which have a common
case for handling "there's no data in this file".
2019-11-12 12:14:29 -06:00
Seebs
6654466033 partially implement truncation of fragments for corrupt ops log
Which is to say don't actually implement it, because openStorage
is too messy right now, but this is the rest of the framework,
and now I'm going to digress into fixing openStorage.
2019-11-12 12:14:29 -06:00
Seebs
538768ea9d handle truncated/damaged .available.shards
The available shards file is just a hint to save us a bit
of time later; we don't need it to run and it can get updated
pretty easily later. If we have problems reading it, we
should just report the error, nuke the file, and continue
without it.
2019-11-12 12:14:29 -06:00
Travis
b8f665db1a pass logger through to the grpc server and handler 2019-11-12 11:08:25 -06:00
seebs
1262cd18e0
Merge pull request #30 from seebs/intfixes
Fix an error that could cause imported values to keep high-order bits from previously imported values, and another that could cause BSI fields to store extra bits they don't need.
2019-11-12 00:02:04 -06:00
seebs
b3adf2d4f6
Merge branch 'enterprise' into q2-11-7 2019-11-11 21:39:45 -06:00
Cody Soyland
5194ede82c
Merge pull request #31 from codysoyland/proto-pkg-name
Change proto package name to "pilosa" to not conflict with molecula
2019-11-11 20:51:52 -06:00
Cody Soyland
69e5e523c1
Merge branch 'enterprise' into proto-pkg-name 2019-11-11 17:26:44 -06:00
Seebs
a804a0dfb1 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.

We also move the computation of requiredDepth, and the change
to the field, down, combining it with the other checks of the
values for min/max being in range.

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.
2019-11-11 16:55:26 -06:00
Travis Turner
1a44f02e3c reset fragment.rowCache after importValue 2019-11-11 16:54:51 -06:00
Travis Turner
10514f7ced
Merge pull request #25 from travisturner/includes-column
Add an IncludesColumn() function to PQL
2019-11-11 12:55:23 -06:00
Cody Soyland
b9335c9f5c Change proto package name to "pilosa" to not conflict with molecula. Upgrade protoc to 3.10.1 2019-11-11 12:24:38 -06:00
Travis
ed37ef5dcf Add an IncludesColumn() function to PQL
Usage:
`IncludesColumn(Intersect(Row(a=1), Row(b=2)), column=10)`

The above query will return a `bool` indicating whether the
intersection of rows a-1 and b-2 contains column 10. Because
a single column is specified, this executes on a single shard
(shard=0 in this example).
2019-11-11 08:17:28 -06:00
Travis Turner
198626e657
Merge pull request #29 from travisturner/linter-fixes
fix golangci-lint complaints
2019-11-11 08:06:35 -06:00
Travis
87b8edc4c5 fix golangci-lint complaints 2019-11-10 17:58:46 -06:00
Travis Turner
2a5d79ad83
Merge pull request #26 from travisturner/proto-licence-exception
add proto/pilosa.pb.go to license.exceptions list
2019-11-10 16:31:00 -06:00
Travis
3129b1c841 add proto/pilosa.pb.go to license.exceptions list 2019-11-10 11:33:29 -06:00
Travis Turner
6632821617
Merge pull request #24 from travisturner/cache-size-none
fix cacheSize when cacheType is none (and cacheSize is 0)
2019-11-08 22:30:17 -06:00
Travis
a842dd521c 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 15:58:49 -06:00
Matthew Jaffee
d6f2196bf1
Merge pull request #16 from pilosa/tls-grpc
use TLS settings when setting up GRPC server or client
2019-10-30 19:35:56 -05:00
Matt Jaffee
6f21887259
use TLS settings when setting up GRPC server or client 2019-10-30 17:38:48 -05:00
Matthew Jaffee
468cf98811
Merge pull request #15 from pilosa/decimal-to-grpc
add decimal field support to Inspect
2019-10-30 13:33:55 -05:00
Matt Jaffee
a414cada4f
add decimal field support to Inspect
I tested this manually with BloomRPC and curl, but need to write real
tests. Also need to get floats for decimal fields coming out of QueryPQL.
2019-10-30 11:13:48 -05:00
Matthew Jaffee
8f64a4f585
Merge pull request #11 from pilosa/decimal-support
support for decimal fields
2019-10-29 16:49:20 -05:00
Matt Jaffee
a9a4d244ef
fix a bug in the "less than" logic 2019-10-29 16:36:15 -05:00
Matt Jaffee
5dcabfcc7f
support for decimal fields
This commit adds a Decimal field type which is implemented mostly with
the Int field. It adds an optional "Scale" value to the Int field
which means that the values stored in that field are actually meant to
be divided by 10^Scale before being interpreted.

In order to make use of this functionality, we extend the importValue
request to allow a slice of floats rather than just int64. If the
slice of floats is present, each float in the slice is multiplied by
10^Scale and converted to an int64 before being imported. If a slice
of int64 is imported to a Decimal field, it is treated normally, and
scale is ignored. This allows the conversion to be handled at the
client side if desired.

Currently there are Field level methods for querying Float values out
of a decimal field, but no support in PQL or the executor for getting
float values. Going to wait until I can use the generic result type
before doing that, so for now, any values queried will be the scaled
integer values.

needed to add client support for importing float values, and did this
by adding a more general and simplified client method for value
imports.

rewrote api.ImportValue to use the new method which should be more
performant and efficient.

allow floats to be "pilosa import"ed into decimal fields
2019-10-29 16:36:14 -05:00
seebs
4ef7f7e26b
Merge pull request #12 from seebs/profile
Profiling and a couple of minor fixes
2019-10-29 15:24:51 -05:00
Seebs
616ed39771 Skip longest tests when running -short
The cluster timeout/down tests are way more than half the total
time for "go test", and are very unlikely to be of interest in regular
usage, although they matter for CI. Skip them when doing short
tests.
2019-10-29 15:24:09 -05:00
Seebs
7a381f7eaf allow years other than 2017 in licenses
Also clean up the license hash checking a bit. We trim vendor early
in find so we don't have to walk the whole vendor tree only to grep
the files out, and we don't check the license hashes of the exceptions,
and the exceptions are now a plain text file of non-regex strings
we match exactly. Also the license hash code is only written once.

This will help us a lot if development on Pilosa continues through
2018 or later.
2019-10-29 15:24:09 -05:00
Seebs
820c5ce220 add trivial execution-time profiling
What if you could ?profile=true on a query and get some
numbers back? That'd be really cool.

We already have tracing/spans, but right now, those only generate
any data if you have something set up for them to trace to. Add a
fancy wrapper that lets us generate our own tracing data, and dump
it into the request response, if ?profile=true.

We track wall-clock execution time, plus possible arbitrary K/V
pairs. Memory stats are not included, because obtaining them is
surprisingly expensive.
2019-10-29 15:23:37 -05:00
Travis Turner
9a2f5b3b4c
Merge pull request #10 from travisturner/grpc
initial gRPC server implementation
2019-10-29 14:39:16 -05:00
Travis
a7bb90fcd0 initial gRPC server implementation
add makeRows() tests
register the gRPC server
use api.Index() instead of api.Schema()

support most field types in Inspect() query

currently, there's no support for `time` fields.
those will be dependent upon the output format
and the ability to materialize the timestamp from
the time views.

this commit also changes the response type of the
`Inspect()` query to be a tabular `RowResponse`.
2019-10-29 14:27:07 -05:00
Travis
77a81eb2e1 fix bug preventing a Rows() query on a bool field 2019-10-29 14:27:07 -05:00
1069 changed files with 203748 additions and 47968 deletions

View file

@ -1,195 +1,305 @@
version: 2
defaults: &defaults
working_directory: /go/src/github.com/pilosa/pilosa
docker:
- image: circleci/golang:1.13
environment:
GO111MODULE: "on"
fast-checkout: &fast-checkout
attach_workspace:
at: .
jobs:
setup:
<<: *defaults
steps:
- checkout
- restore_cache:
keys:
- mod-cache-{{ checksum "go.sum" }}
- run: "go mod download"
- save_cache:
key: mod-cache-{{ checksum "go.sum" }}
paths:
- /go/pkg/mod/
- persist_to_workspace:
root: .
paths: "*"
check-license-headers:
<<: *defaults
steps:
- *fast-checkout
- run: make check-license-headers
linter:
<<: *defaults
steps:
- *fast-checkout
- run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.20.0
- run: sudo cp bin/golangci-lint /usr/local/bin/
- run: make golangci-lint
test-build-arm:
<<: *defaults
steps:
- *fast-checkout
- run: make build GOOS=linux GOARCH=arm GOARM=5
- run: make build GOOS=linux GOARCH=arm GOARM=6
- run: make build GOOS=linux GOARCH=arm GOARM=7
- run: make build GOOS=linux GOARCH=arm64
test-golang-1.13: &base-test
<<: *defaults
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run: make test
test-golang-1.13-shard22:
<<: *defaults
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run: make test SHARD_WIDTH=22
test-golang-1.13-race:
<<: *defaults
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run:
command: make test TESTFLAGS="-race -v -timeout=30m"
no_output_timeout: 30m
test-golang-1.13-386:
<<: *base-test
environment:
GO111MODULE: "on"
GOARCH: 386
test-golang-1.13-enterprise:
<<: *defaults
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run: make test ENTERPRISE=1
test-golang-1.12:
<<: *defaults
docker:
- image: circleci/golang:1.12
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run: make test
test-golang-1.11:
<<: *defaults
docker:
- image: circleci/golang:1.11
steps:
- *fast-checkout
- run: sudo apt-get install lsof
- run: make test
cluster-tests:
<<: *defaults
steps:
- *fast-checkout
- setup_remote_docker
- run: make clustertests-build
prerelease:
<<: *base-test
steps:
- *fast-checkout
- run: make prerelease
- store_artifacts:
path: build
- persist_to_workspace:
root: .
paths: build
release:
<<: *defaults
steps:
- *fast-checkout
- run: make release
- store_artifacts:
path: build
- persist_to_workspace:
root: .
paths: build
prerelease-upload:
docker:
- image: circleci/python:2.7-jessie
steps:
- run: '[[ -v CIRCLE_PR_NUMBER ]] && circleci step halt || true' # Skip job if this is a PR
- *fast-checkout
- run: sudo pip install awscli
- run: make prerelease-upload
dockerhub-upload:
<<: *defaults
steps:
- run: '[[ -v CIRCLE_PR_NUMBER ]] && circleci step halt || true' # Skip job if this is a PR
- *fast-checkout
- setup_remote_docker
- run: make docker
- run: docker tag pilosa:$(git describe --tags) pilosa/pilosa:master
- run: docker login -u $DOCKER_USER -p $DOCKER_PASS
- run: docker push pilosa/pilosa:master
workflows:
version: 2
test:
jobs:
- setup
- linter:
requires:
- setup
- check-license-headers:
requires:
- setup
- test-build-arm:
requires:
- setup
- test-golang-1.13-enterprise:
requires:
- setup
- test-golang-1.13-race:
requires:
- setup
- test-golang-1.13-386:
requires:
- setup
- test-golang-1.13:
requires:
- setup
- test-golang-1.12:
requires:
- setup
- test-golang-1.11:
requires:
- setup
- cluster-tests:
requires:
- setup
- prerelease:
requires:
- linter
- check-license-headers
- test-golang-1.13
- release:
requires:
- linter
- check-license-headers
- test-golang-1.13
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- prerelease-upload:
requires:
- prerelease
- dockerhub-upload:
requires:
- linter
- check-license-headers
- test-golang-1.13
# version: 2.1
# executors:
# golang:
# parameters:
# version:
# type: string
# default: "1.15.8"
# resource_class:
# type: string
# default: medium
# docker:
# - image: circleci/golang:<< parameters.version >>
# resource_class: << parameters.resource_class >>
# working_directory: /go/src/github.com/molecula/featurebase
# commands:
# add-github-auth:
# steps:
# - run: git config --global url."https://${GITHUB_USER}:${GITHUB_PERSONAL_ACCESS_TOKEN}@github.com/".insteadOf "https://github.com/"
# - run: git config --global url."https://${GITHUB_USER}:${GITHUB_PERSONAL_ACCESS_TOKEN}@github.com/".insteadOf "git@github.com:"
# restore-mod-cache:
# steps:
# - restore_cache:
# key: mod-cache-{{ checksum "go.sum" }}
# save-mod-cache:
# steps:
# - save_cache:
# key: mod-cache-{{ checksum "go.sum" }}
# paths:
# - /go/pkg/mod/
# checkout-plus:
# steps:
# - add-github-auth
# - checkout
# - restore-mod-cache
# skip-if-root-unchanged:
# description: "skips the parent job if the PR includes no changes to featurebase"
# steps:
# - run: |
# ROOT_CHANGED_FILES="$(git diff --name-only HEAD $(git merge-base master HEAD) | grep -v '^lattice/')" || true
# echo "ROOT_CHANGED_FILES = $ROOT_CHANGED_FILES"
# if [ -z "$ROOT_CHANGED_FILES" ] ; then
# echo "halting step"
# circleci step halt
# fi
# skip-if-lattice-unchanged:
# description: "skips the parent job if the PR includes no changes to lattice"
# steps:
# - run: |
# LATTICE_CHANGED_FILES="$(git diff --name-only HEAD $(git merge-base master HEAD) | grep '^lattice/')" || true
# echo "LATTICE_CHANGED_FILES = $LATTICE_CHANGED_FILES"
# if [ -z "$LATTICE_CHANGED_FILES" ] ; then
# echo "halting step"
# circleci step halt
# fi
# jobs:
# setup:
# executor:
# name: golang
# steps:
# - checkout-plus
# - run: go mod download
# - save-mod-cache
# linter:
# executor:
# name: golang
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sudo sh -s -- -b /usr/local/bin v1.31.0
# - run: make golangci-lint
# go-mod-tidy:
# executor:
# name: golang
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - run: go mod tidy
# - run: git diff --exit-code -- go.mod go.sum
# check-changelog-label:
# executor:
# name: golang
# steps:
# - run: '[[ -n $CIRCLE_PULL_REQUEST ]] || circleci step halt || true' # Skip if this is not a pull request
# - run: curl https://$GITHUB_USER:$GITHUB_PERSONAL_ACCESS_TOKEN@api.github.com/repos/molecula/featurebase/pulls/$(basename $CIRCLE_PULL_REQUEST) | jq "[.labels[] | .name | startswith(\"changelog\")] | any" -e
# test-build-arm:
# executor:
# name: golang
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - run: make build GOOS=linux GOARCH=arm GOARM=5
# - run: make build GOOS=linux GOARCH=arm GOARM=6
# - run: make build GOOS=linux GOARCH=arm GOARM=7
# - run: make build GOOS=linux GOARCH=arm64
# test:
# parameters:
# resource_class:
# type: string
# default: medium
# golang_version:
# type: string
# default: "1.15.8"
# shard_width:
# type: string
# default: "20"
# test_make_target:
# type: string
# default: "test"
# test_flags:
# type: string
# default: ""
# goarch:
# type: string
# default: amd64
# executor:
# name: golang
# version: << parameters.golang_version >>
# resource_class: << parameters.resource_class >>
# environment:
# TMPDIR: /mnt/ramdisk
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - run: sudo apt-get update --allow-releaseinfo-change -y
# - run: sudo apt-get install lsof
# - run:
# command: make << parameters.test_make_target >> SHARD_WIDTH=<< parameters.shard_width >> GOARCH=<< parameters.goarch >>
# no_output_timeout: 30m
# test-external-lookup:
# docker:
# - image: circleci/golang:1.15.8
# - image: circleci/postgres:13.2-ram
# environment:
# POSTGRES_PASSWORD=password
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - run: sudo apt-get update --allow-releaseinfo-change -y
# - run: sudo apt-get install postgresql-client
# - run: (for i in `seq 1 20`; do pg_isready -h localhost && exit 0 || sleep 1; done; exit 1)
# - run:
# command: make test-external-lookup EXTERNAL_LOOKUP_DSN=postgresql://postgres:password@localhost/circle_test?sslmode=disable
# no_output_timeout: 30m
# cluster-tests:
# executor:
# name: golang
# steps:
# - checkout-plus
# - skip-if-root-unchanged
# - setup_remote_docker
# - run: make clustertests
# release:
# executor:
# name: golang
# steps:
# - checkout-plus
# - attach_workspace:
# at: .
# - setup_remote_docker:
# version: 19.03.13 # see https://support.circleci.com/hc/en-us/articles/360050934711
# - run: echo -n $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
# - run: make docker-release
# - store_artifacts:
# path: build
# - persist_to_workspace:
# root: .
# paths: build
# publish_release:
# executor:
# name: golang
# steps:
# - attach_workspace:
# at: .
# - run: go get github.com/tcnksm/ghr
# - run: ghr -t ${GITHUB_PERSONAL_ACCESS_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./build/
# docker-build:
# executor:
# name: golang
# steps:
# - checkout-plus
# - setup_remote_docker:
# version: 19.03.13 # see https://support.circleci.com/hc/en-us/articles/360050934711
# - run: echo -n $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
# - run: make docker GO_VERSION=1.15.8
# - run: docker run featurebase:$(git describe --tags) help
# dockerhub-upload-unstable:
# executor:
# name: golang
# steps:
# - checkout-plus
# - setup_remote_docker:
# version: 19.03.13 # see https://support.circleci.com/hc/en-us/articles/360050934711
# - run: echo -n $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
# - run: make docker
# - run: docker run featurebase:$(git describe --tags) help
# - run: make docker-tag-push DOCKER_TARGET=moleculacorp/featurebase:<< pipeline.git.branch >>
# dockerhub-upload-stable:
# executor:
# name: golang
# steps:
# - checkout-plus
# - setup_remote_docker:
# version: 19.03.13 # see https://support.circleci.com/hc/en-us/articles/360050934711
# - run: echo -n $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
# - run: make docker
# - run: docker run featurebase:$(git describe --tags) help
# - run: make docker-tag-push DOCKER_TARGET=moleculacorp/featurebase:<< pipeline.git.tag >>
# - run: make docker-tag-push DOCKER_TARGET=moleculacorp/featurebase:latest
# workflows:
# build:
# jobs:
# - setup:
# context: molecula
# filters:
# tags:
# only: /^v.*/
# - linter:
# context: molecula
# requires:
# - setup
# - go-mod-tidy:
# context: molecula
# requires:
# - setup
# - check-changelog-label:
# context: molecula
# requires:
# - setup
# - test-build-arm:
# context: molecula
# requires:
# - setup
# - test:
# name: test-golang-<< matrix.golang_version >>
# resource_class: large
# context: molecula
# requires:
# - setup
# matrix:
# parameters:
# golang_version: ["1.15.8", "1.16.10"]
# - test:
# name: << matrix.test_make_target >>
# resource_class: xlarge
# context: molecula
# requires:
# - setup
# matrix:
# parameters:
# test_make_target: ["test-race"]
# - test:
# name: test-shardwidth-22
# context: molecula
# shard_width: "22"
# resource_class: large
# requires:
# - setup
# - test-external-lookup:
# context: molecula
# requires:
# - setup
# - cluster-tests:
# context: molecula
# requires:
# - setup
# - docker-build:
# context: molecula
# requires:
# - setup
# - release:
# context: molecula
# requires:
# - setup
# filters:
# tags:
# only: /^v.*/
# - publish_release:
# context: molecula
# requires:
# - release
# filters:
# tags:
# only: /^v.*/
# branches:
# ignore: /.*/
# - dockerhub-upload-unstable:
# context: molecula
# requires:
# - setup
# filters:
# branches:
# only: master
# - dockerhub-upload-stable:
# context: molecula
# requires:
# - setup
# filters:
# tags:
# only: /^v.*/
# branches:
# ignore: /.*/

5
.dockerignore Normal file
View file

@ -0,0 +1,5 @@
lattice/.git
lattice/node_modules
lattice/build
statik/statik.go
build

View file

@ -6,13 +6,10 @@ 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 updated the [documentation](https://github.com/molecula/docs).
- [ ] I have resolved any merge conflicts.
- [ ] I have included tests that cover my changes.
- [ ] All new and existing tests pass.
- [ ] Make sure PR title conforms to convention in CHANGELOG.md.
- [ ] Add appropriate changelog label to PR (if applicable).
## Code review checklist
@ -24,5 +21,4 @@ This is the checklist that the reviewer will follow while reviewing your pull re
- [ ] 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.
- [ ] Make sure PR title conforms to convention in CHANGELOG.md.
- [ ] Make sure PR is tagged with appropriate changelog label.

17
.gitignore vendored
View file

@ -4,3 +4,20 @@ 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/

522
.gitlab/.gitlab-ci.yml Normal file
View file

@ -0,0 +1,522 @@
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
GOVERSION: "1.16.13"
stages:
- lint
- test
- build
- integration
- gauntlet
- performance
- post build
smoke build:
image: golang:$GOVERSION
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.39.0
stage: lint
allow_failure: false
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
build lattice:
stage: test
image: node:14
variables:
CI: "false"
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- cd lattice
- yarn install
- yarn build
- mv build ../
- cd ../
- rm -r lattice
- mv build lattice
- tar -czvf lattice.tar.gz lattice
artifacts:
paths:
- lattice.tar.gz
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
run go tests:
stage: test
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
retry: 1
script:
- echo "Running featurebase unit tests..."
- go test -timeout=30m ./...
tags:
- aws
run go tests race:
stage: test
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
retry: 1
script:
- echo "Running featurebase race tests..."
- go test -race -v -timeout=90m ./...
tags:
- aws
run go tests shardwidth22:
stage: test
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- echo "Running featurebase race tests..."
- go test -timeout=30m -tags=shardwidth22 ./...
tags:
- aws
# we do coverage reporting from the future tests because the json
# output is very difficult to human-read. The alternative would be to
# run the regular tests twice and also run the future tests.
run go tests future:
stage: test
image: golang:1.17.6
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
retry: 1
script:
- echo "Running featurebase unit tests..."
- PKG_LIST=$(go list ./... | grep -v internal/clustertests | paste -s -d, -)
- go test -timeout=30m -json -coverprofile=coverage.out -covermode=atomic -coverpkg=${PKG_LIST} ./... | tee test-report.out
artifacts:
paths:
- coverage.out
- test-report.out
tags:
- aws
upload to sonarcloud:
stage: integration
image: sonarsource/sonar-scanner-cli:4.6
variables:
SONAR_TOKEN: $SONAR_TOKEN
rules:
- if: '$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 -Dsonar.go.tests.reportPaths=test-report.out,results/report* -Dsonar.javascript.lcov.reportPaths=lattice/coverage/lcov.info
needs:
- job: run go tests future
- job: run jest tests
- job: clustertests
build for linux amd64:
stage: build
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -r lattice
- tar -xvf lattice.tar.gz
- go get -v -u github.com/rakyll/statik
- /go/bin/statik -src=lattice
- GOOS="linux" GOARCH="amd64" make build FLAGS="-o featurebase_linux_amd64"
- GOOS="linux" GOARCH="amd64" go build -o roaring-migrate_linux_amd64 ./cmd/roaring-migrate
artifacts:
paths:
- featurebase_linux_amd64
- roaring-migrate_linux_amd64
build for linux arm64:
stage: build
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -r lattice
- tar -xvf lattice.tar.gz
- go get -v -u github.com/rakyll/statik
- /go/bin/statik -src=lattice
- GOOS="linux" GOARCH="arm64" make build FLAGS="-o featurebase_linux_arm64"
- GOOS="linux" GOARCH="arm64" go build -o roaring-migrate_linux_arm64 ./cmd/roaring-migrate
artifacts:
paths:
- featurebase_linux_arm64
- roaring-migrate_linux_arm64
build for darwin amd64:
stage: build
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -r lattice
- tar -xvf lattice.tar.gz
- go get -v -u github.com/rakyll/statik
- /go/bin/statik -src=lattice
- GOOS="darwin" GOARCH="amd64" make build FLAGS="-o featurebase_darwin_amd64"
- GOOS="darwin" GOARCH="amd64" go build -o roaring-migrate_darwin_amd64 ./cmd/roaring-migrate
artifacts:
paths:
- featurebase_darwin_amd64
- roaring-migrate_darwin_amd64
build for darwin arm64:
stage: build
image: golang:$GOVERSION
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -r lattice
- tar -xvf lattice.tar.gz
- go get -v -u github.com/rakyll/statik
- /go/bin/statik -src=lattice
- GOOS="darwin" GOARCH="arm64" make build FLAGS="-o featurebase_darwin_arm64"
- GOOS="darwin" GOARCH="arm64" go build -o roaring-migrate_darwin_arm64 ./cmd/roaring-migrate
artifacts:
paths:
- featurebase_darwin_arm64
- roaring-migrate_darwin_arm64
package for linux amd64:
stage: build
image: golang:$GOVERSION
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"
package for linux arm64:
stage: build
image: golang:$GOVERSION
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 amd container fb:
stage: build
needs:
- "build for linux amd64"
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}
- docker build --build-arg GO_VERSION=$GOVERSION --build-arg ARCH=amd64 -t $tag -f .gitlab/Dockerfile .
- docker push $tag
- echo Created docker featurebase image with tag "$tag"
build arm container fb:
stage: build
needs:
- "build for linux arm64"
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-arm64-${CI_COMMIT_REF_SLUG}
- docker build --build-arg GO_VERSION=$GOVERSION --build-arg ARCH=arm64 -t $tag -f .gitlab/Dockerfile .
- docker push $tag
- echo Created docker featurebase image with tag "$tag"
# clustertests doesn't run in docker, and requires several things to be set up on the runner to work:
# 1. Install Go, make sure it's on the path
# 2. Make sure "make" is installed
# 3. make sure docker/docker-compose is installed
# 4. make sure the git config is done `git config --global --add url."ssh://git@github.com/".insteadOf "https://github.com/"`
# 5. Add deploy key github.com/molecula/featurebase/settings/keys and add public key in .ssh folder of gitlab-runner user
# TODO: (I think) get clustertests coverage added to coverage report
clustertests:
variables:
PROJECT: clustertests_${CI_CONCURRENT_ID}
stage: integration
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -rf internal/clustertests/results && mkdir -p internal/clustertests/results && chown gitlab-runner:gitlab-runner internal/clustertests/results
- make clustertests
- mv internal/clustertests/results/ results/
artifacts:
paths:
- results/coverage*.out
authclustertests:
variables:
PROJECT: authclustertests_${CI_CONCURRENT_ID}
stage: integration
tags:
- shell
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
script:
- rm -rf internal/clustertests/results && mkdir -p internal/clustertests/results && chown gitlab-runner:gitlab-runner internal/clustertests/results
- make authclustertests
- rm -rf internal/clustertests/results
external lookup tests:
stage: integration
image: golang:$GOVERSION
# 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
smoke test:
stage: integration
image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest
variables:
PROFILE: "service-terraform"
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
TF_VAR_cluster_prefix: ""
tags:
- aws
- docker
- fbsmoke
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
before_script:
- apt-get update && apt-get install -y gnupg software-properties-common curl git
- curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
- apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
- apt-get update && apt-get install terraform
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID --profile $PROFILE
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY --profile $PROFILE
- aws configure set region "us-east-2" --profile $PROFILE
- aws configure set aws_profile $PROFILE
- echo $AWS_FBCI_SSH_KEY > gitlab-featurebase-ci.pem
- chmod 400 gitlab-featurebase-ci.pem
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- echo $AWS_FBCI_SSH_KEY > /root/.ssh/gitlab-featurebase-ci.pem
- chmod 400 /root/.ssh/gitlab-featurebase-ci.pem
- echo "$AWS_FBCI_SSH_KEY" | ssh-add -
- chmod 700 /root/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- apt update && apt -y install jq wget
- wget -q https://go.dev/dl/go1.17.5.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- TF_VAR_cluster_prefix="smoke-$(openssl rand -base64 12 | tr -d /=+ | cut -c -16)"
- echo "Cluster Prefix --> $TF_VAR_cluster_prefix"
script:
- ./qa/scripts/setupSmokeTest.sh
- ./qa/scripts/testSmokeTest.sh
after_script:
- ./qa/scripts/teardownSmokeTest.sh
needs:
- job: build for linux arm64
artifacts:
when: always
paths:
- report.xml
reports:
junit: report.xml
gauntlet:
stage: gauntlet
timeout: 4h
image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest
variables:
FBCI_PROFILE: "service-terraform"
INFRA_PROFILE: "service-gitlab"
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
ASG_NAME: "gitlab-runners"
TF_VAR_cluster_prefix: ""
tags:
- aws
- docker
- fbsmoke
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && ($CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web")'
before_script:
- apt-get update && apt-get install -y gnupg software-properties-common curl git
- curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
- apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
- apt-get update && apt-get install terraform
- aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID --profile $FBCI_PROFILE
- aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY --profile $FBCI_PROFILE
- aws configure set region "us-east-2" --profile $FBCI_PROFILE
- aws configure set aws_profile $FBCI_PROFILE
- aws configure set aws_access_key_id $AWS_INFRA_ACCESS_KEY_ID --profile $INFRA_PROFILE
- aws configure set aws_secret_access_key $AWS_INFRA_SECRET_ACCESS_KEY --profile $INFRA_PROFILE
- aws configure set region "us-east-2" --profile $INFRA_PROFILE
- echo $AWS_FBCI_SSH_KEY > gitlab-featurebase-ci.pem
- chmod 400 gitlab-featurebase-ci.pem
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- echo $AWS_FBCI_SSH_KEY > /root/.ssh/gitlab-featurebase-ci.pem
- chmod 400 /root/.ssh/gitlab-featurebase-ci.pem
- echo "$AWS_FBCI_SSH_KEY" | ssh-add -
- chmod 700 /root/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- apt update && apt -y install jq wget
- wget -q https://go.dev/dl/go1.17.5.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- TF_VAR_cluster_prefix="gauntlet-$(openssl rand -base64 12 | tr -d /=+ | cut -c -16)"
- echo "Cluster Prefix --> $TF_VAR_cluster_prefix"
- export INSTANCE_ID=$(curl --silent --fail "http://169.254.169.254/latest/meta-data/instance-id" | tee instance_id)
- aws autoscaling set-instance-protection --instance-ids "$INSTANCE_ID" --auto-scaling-group-name $ASG_NAME --protected-from-scale-in --profile $INFRA_PROFILE
script:
- ./qa/scripts/setupSamsungGauntlet.sh
- ./qa/scripts/testSamsungGauntlet.sh
after_script:
- ./qa/scripts/teardownSamsungGauntlet.sh || true # leaving dangling resources is better than dangling ASG instances that can't be terminated
- export INSTANCE_ID=$(cat instance_id)
- aws autoscaling set-instance-protection --instance-ids "$INSTANCE_ID" --auto-scaling-group-name $ASG_NAME --no-protected-from-scale-in --profile $INFRA_PROFILE
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_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
- aws s3 cp featurebase_linux_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/featurebase_linux_amd64
- aws s3 cp featurebase_linux_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/featurebase_linux_amd64
- aws s3 cp roaring-migrate_linux_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/roaring-migrate_linux_amd64
- aws s3 cp roaring-migrate_linux_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/roaring-migrate_linux_amd64
- aws s3 cp featurebase_linux_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/featurebase_linux_arm64
- aws s3 cp featurebase_linux_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/featurebase_linux_arm64
- aws s3 cp roaring-migrate_linux_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/roaring-migrate_linux_arm64
- aws s3 cp roaring-migrate_linux_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/roaring-migrate_linux_arm64
- aws s3 cp featurebase_darwin_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/featurebase_darwin_amd64
- aws s3 cp featurebase_darwin_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/featurebase_darwin_amd64
- aws s3 cp roaring-migrate_darwin_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/roaring-migrate_darwin_amd64
- aws s3 cp roaring-migrate_darwin_amd64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/roaring-migrate_darwin_amd64
- aws s3 cp featurebase_darwin_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/featurebase_darwin_arm64
- aws s3 cp featurebase_darwin_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/featurebase_darwin_arm64
- aws s3 cp roaring-migrate_darwin_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/${CI_COMMIT_SHORT_SHA}/roaring-migrate_darwin_arm64
- aws s3 cp roaring-migrate_darwin_arm64 s3://molecula-artifact-storage/featurebase/${CI_COMMIT_BRANCH}/_latest/roaring-migrate_darwin_arm64
needs:
- job: build for darwin amd64
- job: build for darwin arm64
- job: build for linux amd64
- job: build for linux arm64
perf_able:
stage: performance
trigger:
include: .gitlab/.perf-able-gitlab-ci.yml
rules:
- changes:
- featurebase/*
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 == "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 featurebase_linux_amd64 s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase_linux_amd64
- aws s3 cp roaring-migrate_linux_amd64 s3://${LOCATION}/${CI_COMMIT_TAG}/roaring-migrate_linux_amd64
- aws s3 cp featurebase_linux_arm64 s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase_linux_arm64
- aws s3 cp roaring-migrate_linux_arm64 s3://${LOCATION}/${CI_COMMIT_TAG}/roaring-migrate_linux_arm64
- aws s3 cp featurebase_darwin_amd64 s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase_darwin_amd64
- aws s3 cp roaring-migrate_darwin_amd64 s3://${LOCATION}/${CI_COMMIT_TAG}/roaring-migrate_darwin_amd64
- aws s3 cp featurebase_darwin_arm64 s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase_darwin_arm64
- aws s3 cp roaring-migrate_darwin_arm64 s3://${LOCATION}/${CI_COMMIT_TAG}/roaring-migrate_darwin_arm64
- aws s3 cp NOTICE s3://${LOCATION}/${CI_COMMIT_TAG}/NOTICE
- aws s3 cp install/featurebase.debian.service s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase.debian.service
- aws s3 cp install/featurebase.redhat.service s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase.redhat.service
- aws s3 cp install/featurebase.conf s3://${LOCATION}/${CI_COMMIT_TAG}/featurebase.conf
needs:
- job: build for darwin amd64
- job: build for darwin arm64
- job: build for linux amd64
- job: build for linux arm64

View file

@ -0,0 +1,11 @@
stages:
- loadtest
loadtest:
image:
name: loadimpact/k6:latest
entrypoint: ['']
stage: loadtest
script:
- echo "executing local k6 in k6 container..."
- k6 run ./qa/scripts/perf/able/script.js

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"]

60
.golangci.yml Normal file
View file

@ -0,0 +1,60 @@
run:
#skip the protobuf generated files
deadline: 5m
timeout: 5m
skip-dirs-use-default: true
skip-dirs:
- pb
- proto
skip-files:
- pql/pql.peg.go
linters:
enable:
- govet
- gofmt
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
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,715 +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/).
## [1.4.0] - 2019-09-17
This version contains 99 contributions from 11 contributors. There are 94 files changed; 9,453 insertions; and 6,121 deletions.
**Attention**: Pilosa 1.4.0 changes the way that integer fields are stored. The upgrade from old format to new is handled automatically, however you will not be able to downgrade to 1.3 should you wish to do so. We *always* recommend taking a backup of your Pilosa data directory before upgrading Pilosa, but doubly so with this release.
### Added
- Update "Getting Started" documentation ([#2028](https://github.com/pilosa/pilosa/pull/2028))
- Add ability to disable tracing and use nopTracer ([#2029](https://github.com/pilosa/pilosa/pull/2029))
- Add test for no containers ([#2016](https://github.com/pilosa/pilosa/pull/2016))
- Add naive implementations of Roaring and fuzz test ([#2023](https://github.com/pilosa/pilosa/pull/2023))
- Add fuzzing code and readme.md to explain the fuzzer ([#2004](https://github.com/pilosa/pilosa/pull/2004))
- Add MinRow and MaxRow calls ([#1983](https://github.com/pilosa/pilosa/pull/1983))
- Add Prometheus stats backend ([#1992](https://github.com/pilosa/pilosa/pull/1992))
- Add extra tracing spans and metadata ([#1939](https://github.com/pilosa/pilosa/pull/1939))
- Add more Debugf() statements to the holder open process ([#1950](https://github.com/pilosa/pilosa/pull/1950))
- Add ability to post schema using holder.applySchema ([#1956](https://github.com/pilosa/pilosa/pull/1956))
### Changed
- Update CircleCI build with Go 1.13 and run enterprise tests ([#2064](https://github.com/pilosa/pilosa/pull/2064))
- Update Alpine to 3.9.4 in Dockerfile ([#2001](https://github.com/pilosa/pilosa/pull/2001))
- Add Prometheus tests, refactor http stats as middleware, minor fixes ([#1994](https://github.com/pilosa/pilosa/pull/1994))
- Add confirmation logic to catch false nodeLeave events ([#1993](https://github.com/pilosa/pilosa/pull/1993))
- Improve TopN() errors ([#1978](https://github.com/pilosa/pilosa/pull/1978))
- Make integer fields unbounded by using sign+magnitude representation ([#1902](https://github.com/pilosa/pilosa/pull/1902))
- Simplify contributing instructions by removing weird upstream thing ([#1966](https://github.com/pilosa/pilosa/pull/1966))
### Fixed
- Default BSI base value to min, max, or 0 depending on the min/max range ([#2050](https://github.com/pilosa/pilosa/pull/2050))
- Add worker pool for query processing ([#2034](https://github.com/pilosa/pilosa/pull/2034))
- Move Range deprecation message to higher level ([#2033](https://github.com/pilosa/pilosa/pull/2033))
- Use lock in view.deleteFragment while altering fragments ([#2026](https://github.com/pilosa/pilosa/pull/2026))
- Fix malformed offset bug in readOffsets and readWithRuns ([#2021](https://github.com/pilosa/pilosa/pull/2021))
- Fix various container iteration bugs in Roaring ([#2019](https://github.com/pilosa/pilosa/pull/2019))
- Fix malformed bitmap handling ([#2017](https://github.com/pilosa/pilosa/pull/2017))
- Fix fuzzer errors in roaring ([#2012](https://github.com/pilosa/pilosa/pull/2012))
- Save all state files atomically to avoid corruption ([#2000](https://github.com/pilosa/pilosa/pull/2000))
- Fix slice container updates ([#1997](https://github.com/pilosa/pilosa/pull/1997))
- Fix out of bounds panic to show error ([#1975](https://github.com/pilosa/pilosa/pull/1975))
- Fix error message returned by regex on field and index names ([#1973](https://github.com/pilosa/pilosa/pull/1973))
- Fix filter calls in GroupBy not being translated ([#1970](https://github.com/pilosa/pilosa/pull/1970))
- Fix TranslateFile behavior when reopened ([#1954](https://github.com/pilosa/pilosa/pull/1954))
- Remove buggy shard validation code ([#1951](https://github.com/pilosa/pilosa/pull/1951))
- Fix some lint warnings raised in VS-Code ([#1947](https://github.com/pilosa/pilosa/pull/1947))
### Performance
- Address some startup speed and performance issues ([#1988](https://github.com/pilosa/pilosa/pull/1988))
- Add a worker pool for importRoaring jobs ([#2048](https://github.com/pilosa/pilosa/pull/2048))
- Use UnionInPlace for computing time rows which involve multiple views ([#2041](https://github.com/pilosa/pilosa/pull/2041))
- Improve ingest performance with snapshot queue and unmarshaling improvements ([#2024](https://github.com/pilosa/pilosa/pull/2024))
- Improve row cache ([#1974](https://github.com/pilosa/pilosa/pull/1974))
### Removed
- Remove extraneous stat tags to improve prometheus performance ([#1996](https://github.com/pilosa/pilosa/pull/1996))
## [1.3.1] - 2019-05-01
This version contains 1 contribution from 1 contributor. There are 6 files changed; 10 insertions; and 95 deletions.
### Fixed
- Remove shard validation to fix bug where some nodes weren't loading their fragments. #1951 ([#1964](https://github.com/pilosa/pilosa/pull/1964))
## [1.3.0] - 2019-04-16
This version contains 98 contributions from 10 contributors. There are 144 files changed; 12,635 insertions; and 4,341 deletions.
### Added
- Add license headers and CI check ([#1940](https://github.com/pilosa/pilosa/pull/1940))
- Add support to modify shard width at build time ([#1921](https://github.com/pilosa/pilosa/pull/1921))
- Add 'bench' Makefile target and run fewer concurrency level benchmarks ([#1915](https://github.com/pilosa/pilosa/pull/1915))
- Add server stats to /info endpoint ([#1859](https://github.com/pilosa/pilosa/pull/1859))
- Implement config options for block profile rate and mutex fraction ([#1910](https://github.com/pilosa/pilosa/pull/1910))
- Implement global open file counter using syswrap (to scale past system open file limits) ([#1906](https://github.com/pilosa/pilosa/pull/1906))
- Implement global mmap counter with fallback (to scale past system mmap limits) ([#1903](https://github.com/pilosa/pilosa/pull/1903))
- Add shard width to index info in schema (allows client to get shard width at run time) ([#1881](https://github.com/pilosa/pilosa/pull/1881))
- Add shift operator ([#1761](https://github.com/pilosa/pilosa/pull/1761))
- Support advertise address and listen on 0.0.0.0 ([#1832](https://github.com/pilosa/pilosa/pull/1832))
- Added convenience function to efficiently calculate size of a roaring bitmap in bytes ([#1839](https://github.com/pilosa/pilosa/pull/1839))
- Make sure more tests and benchmarks can have their temp dir set by flag ([#1831](https://github.com/pilosa/pilosa/pull/1831))
- Add sliceascending/slicedescending striped benchmarks ([#1763](https://github.com/pilosa/pilosa/pull/1763))
- Add setValue test and benchmarks ([#1820](https://github.com/pilosa/pilosa/pull/1820))
- Add a test for groupby filter with RangeLTLT ([#1818](https://github.com/pilosa/pilosa/pull/1818))
- Add tests for GroupBy with keys; removes unused Bit message from proto ([#1811](https://github.com/pilosa/pilosa/pull/1811))
### Fixed
- Update to latest memberlist fork with race fixes ([#1944](https://github.com/pilosa/pilosa/pull/1944))
- Return original error instead of cause in handler ([#1943](https://github.com/pilosa/pilosa/pull/1943))
- Validate (and panic) on duplicate PQL arguments ([#1938](https://github.com/pilosa/pilosa/pull/1938))
- Add correct content type to query responses Fixes #1873 ([#1936](https://github.com/pilosa/pilosa/pull/1936))
- Address race condition by getting cluster nodes with lock ([#1931](https://github.com/pilosa/pilosa/pull/1931))
- Make sure to unmap containers before modifying ([#1876](https://github.com/pilosa/pilosa/pull/1876))
- Avoid probable race when creating fragments ([#1863](https://github.com/pilosa/pilosa/pull/1863))
- Improve help strings for metrics options ([#1887](https://github.com/pilosa/pilosa/pull/1887))
- Ensure ClearRow() arguments get translated ([#1848](https://github.com/pilosa/pilosa/pull/1848))
- Prevent omitting zero ids on columnattrs ([#1846](https://github.com/pilosa/pilosa/pull/1846))
- Set cache size to 0 if cache type is none ([#1842](https://github.com/pilosa/pilosa/pull/1842))
- Prevent deadlock in replication logic on reopening a store ([#1834](https://github.com/pilosa/pilosa/pull/1834))
- Pass loggers around properly in gossip ([#1835](https://github.com/pilosa/pilosa/pull/1835))
- Include read lock in cluster.Nodes() ([#1836](https://github.com/pilosa/pilosa/pull/1836))
- Raise an error on Rows() query against a time field with noStandardView: true ([#1826](https://github.com/pilosa/pilosa/pull/1826))
- Don't delete test fragment data (part of repo) ([#1827](https://github.com/pilosa/pilosa/pull/1827))
- Fix bug on upper end of bsi range queries ([#1822](https://github.com/pilosa/pilosa/pull/1822))
- Group by fixes ([#1802](https://github.com/pilosa/pilosa/pull/1802))
### Changed
- Switch to GolangCI lint ([#1924](https://github.com/pilosa/pilosa/pull/1924))
- Return empty result set when query empty ([#1937](https://github.com/pilosa/pilosa/pull/1937))
- Add Go 1.12 to CircleCI ([#1909](https://github.com/pilosa/pilosa/pull/1909))
- Ignore fragment files from shards node doesn't own ([#1900](https://github.com/pilosa/pilosa/pull/1900))
- Go module support. Use Modules instead of dep for dependencies ([#1616](https://github.com/pilosa/pilosa/pull/1616))
- Merge Range() into Row() call. ([#1804](https://github.com/pilosa/pilosa/pull/1804))
- Add from/to range arguments to Rows() call ([#1851](https://github.com/pilosa/pilosa/pull/1851))
- Fixes Store call error messages, Rows doesn't need field argument ([#1830](https://github.com/pilosa/pilosa/pull/1830))
### Performance
- BTree performance improvements ([#1916](https://github.com/pilosa/pilosa/pull/1916))
- Make Containers smaller, especially when they have small contents ([#1901](https://github.com/pilosa/pilosa/pull/1901))
- Address UnionInPlace performance regressions ([#1897](https://github.com/pilosa/pilosa/pull/1897))
- Small write path for import-roaring. Makes small imports faster ([#1892](https://github.com/pilosa/pilosa/pull/1892))
- Small write path for imports ([#1871](https://github.com/pilosa/pilosa/pull/1871))
- Remove copy for pilosa roaring files ([#1865](https://github.com/pilosa/pilosa/pull/1865))
- Disable anti-entropy if not using replication [performance] ([#1814](https://github.com/pilosa/pilosa/pull/1814))
- Group By—skip 0 counts as early as possible ([#1803](https://github.com/pilosa/pilosa/pull/1803))
## [1.2.0] - 2018-12-20
This version contains 155 contributions from 11 contributors. There are 113 files changed; 19,085 insertions; and 4,323 deletions.
### Added
- Cancel queries on Context.Done() ([#1773](https://github.com/pilosa/pilosa/pull/1773))
- Union In Place ([#1766](https://github.com/pilosa/pilosa/pull/1766), [#1774](https://github.com/pilosa/pilosa/pull/1774))
- Import benchmarking ([#1771](https://github.com/pilosa/pilosa/pull/1771))
- Add GroupBy() Filter ([#1753](https://github.com/pilosa/pilosa/pull/1753))
- Add /internal/translate/keys endpoint ([#1751](https://github.com/pilosa/pilosa/pull/1751))
- CircleCI: Add race detector to parallel build, default to Go 1.11. ([#1756](https://github.com/pilosa/pilosa/pull/1756))
- Add distributed tracing. ([#1684](https://github.com/pilosa/pilosa/pull/1684))
- Add NoStandardView field option ([#1733](https://github.com/pilosa/pilosa/pull/1733))
- Add some stat tracking to roaring implementation ([#1743](https://github.com/pilosa/pilosa/pull/1743))
- Add cluster fault testing using docker-compose and pumba ([#1717](https://github.com/pilosa/pilosa/pull/1717))
- Allow backslash, carriage return in PQL strings ([#1713](https://github.com/pilosa/pilosa/pull/1713))
- Add base system, curl and jq for debug and checks ([#1707](https://github.com/pilosa/pilosa/pull/1707))
- Add `Rows` and `GroupBy` functionality ([#1647](https://github.com/pilosa/pilosa/pull/1647))
- Add `clear` functional option for imports ([#1699](https://github.com/pilosa/pilosa/pull/1699))
- Implement tracking of available shards to help support sparse datasets ([#1600](https://github.com/pilosa/pilosa/pull/1600), [#1695](https://github.com/pilosa/pilosa/pull/1695), [#1624](https://github.com/pilosa/pilosa/pull/1624), [#1663](https://github.com/pilosa/pilosa/pull/1663))
- Add missing rowID/Key columnID/Key tests ([#1683](https://github.com/pilosa/pilosa/pull/1683))
- Add Store() operation to PQL ([#1666](https://github.com/pilosa/pilosa/pull/1666))
- Add diagnostics CPUArch field ([#1671](https://github.com/pilosa/pilosa/pull/1671))
- Add CircleCI step to generate Docker image and push to Docker hub ([#1673](https://github.com/pilosa/pilosa/pull/1673))
- Implement ClearRow() query ([#1645](https://github.com/pilosa/pilosa/pull/1645))
- Add support for Bool fields ([#1658](https://github.com/pilosa/pilosa/pull/1658))
- Make translate map size configurable ([#1653](https://github.com/pilosa/pilosa/pull/1653))
- Add DirectAdd function to roaring.Bitmap ([#1646](https://github.com/pilosa/pilosa/pull/1646))
- Implement Roaring import ([#1622](https://github.com/pilosa/pilosa/pull/1622), [#1738](https://github.com/pilosa/pilosa/pull/1738))
- Add Not() query ([#1635](https://github.com/pilosa/pilosa/pull/1635))
- Implement Options call and excludeRowAttrs, excludeColumns, columnAttrs and shards args ([#1631](https://github.com/pilosa/pilosa/pull/1631))
- Add field options to pilosa import ([#1625](https://github.com/pilosa/pilosa/pull/1625))
- Implement column existence tracking ([#1788](https://github.com/pilosa/pilosa/pull/1788), [#1672](https://github.com/pilosa/pilosa/pull/1672), [#1628](https://github.com/pilosa/pilosa/pull/1628))
### Changed
- Convert the anti-entropy logic to use `ImportRoaring` instead of `QueryNode` ([#1780](https://github.com/pilosa/pilosa/pull/1780))
- Simplify `require-*` logic in Makefile ([#1755](https://github.com/pilosa/pilosa/pull/1755))
- Cleanup logging ([#1748](https://github.com/pilosa/pilosa/pull/1748))
- Remove TravisCI, add CircleCI shield ([#1740](https://github.com/pilosa/pilosa/pull/1740))
- Upgrade Peg dependency and regenerate grammar ([#1725](https://github.com/pilosa/pilosa/pull/1725))
- Upgrade to protoc 3.6.1 (also updated protoc-gen-gofast) ([#1724](https://github.com/pilosa/pilosa/pull/1724))
- Move column attrs logic to executor ([#1677](https://github.com/pilosa/pilosa/pull/1677))
- Shrink container bit count to int32 ([#1664](https://github.com/pilosa/pilosa/pull/1664))
### Performance
- Remove bounds check ([#1619](https://github.com/pilosa/pilosa/pull/1619))
- Improve benchmarking and performance ([#1741](https://github.com/pilosa/pilosa/pull/1741))
### Fixed
- Ensure internal client closes all response bodies ([#1795](https://github.com/pilosa/pilosa/pull/1795))
- Allow translate log entry buffer to grow ([#1787](https://github.com/pilosa/pilosa/pull/1787))
- Add Gopkg.lock as a dependency for vendor target ([#1790](https://github.com/pilosa/pilosa/pull/1790))
- Cluster resize fix ([#1785](https://github.com/pilosa/pilosa/pull/1785))
- Attempt to fix deadlock by releasing view lock before broadcasting ([#1782](https://github.com/pilosa/pilosa/pull/1782))
- Fix bug where cluster goes into RESIZING instead of NORMAL ([#1777](https://github.com/pilosa/pilosa/pull/1777))
- Propogate updates to node details (not just additions and deletions) ([#1769](https://github.com/pilosa/pilosa/pull/1769))
- Fix arm64 support ([#1764](https://github.com/pilosa/pilosa/pull/1764))
- Fix data races ([#1750](https://github.com/pilosa/pilosa/pull/1750))
- Fix fragment checksums race condition ([#1749](https://github.com/pilosa/pilosa/pull/1749))
- Import cmd field type flag ([#1732](https://github.com/pilosa/pilosa/pull/1732))
- Increase the translate file size for tests/benchmarks ([#1744](https://github.com/pilosa/pilosa/pull/1744))
- Prevent panic in Bitmap.UnmarshalBinary when there is no data ([#1742](https://github.com/pilosa/pilosa/pull/1742))
- Remove unused rule from peg grammar ([#1737](https://github.com/pilosa/pilosa/pull/1737))
- Improve Internal Client errors ([#1729](https://github.com/pilosa/pilosa/pull/1729))
- Forward imports to non-coordinator shards ([#1719](https://github.com/pilosa/pilosa/pull/1719))
- Fix double escapes in PQL grammar ([#1727](https://github.com/pilosa/pilosa/pull/1727))
- Ensure btree comparison doesn't fail for smallish N ([#1712](https://github.com/pilosa/pilosa/pull/1712))
- Drop now-superfluous methodNotAllowedHandler ([#1711](https://github.com/pilosa/pilosa/pull/1711))
- Use pilosa.Logger everywhere ([#1674](https://github.com/pilosa/pilosa/pull/1674))
- Ensure view closes fragment on broadcast error ([#1675](https://github.com/pilosa/pilosa/pull/1675))
- Prevent closing os.Stderr (used in verbose test logging) ([#1696](https://github.com/pilosa/pilosa/pull/1696))
- Allow holder to close/open/close without panic on closing closed channel ([#1686](https://github.com/pilosa/pilosa/pull/1686))
- Fix bug with Range() queries with field keys ([#1679](https://github.com/pilosa/pilosa/pull/1679))
- Sync query validation for handlers ([#1676](https://github.com/pilosa/pilosa/pull/1676))
- Wrap translation store errors, decrease test map size to prevent failure on 32-bit ([#1665](https://github.com/pilosa/pilosa/pull/1665))
- Fix pass-by-value issue in proto decode ([#1662](https://github.com/pilosa/pilosa/pull/1662))
- Do not run prerelease in CI if this is a pull request ([#1655](https://github.com/pilosa/pilosa/pull/1655))
- Ensure mutex imports unset previous columns ([#1656](https://github.com/pilosa/pilosa/pull/1656))
- Treat import timestamps as UTC ([#1651](https://github.com/pilosa/pilosa/pull/1651))
- Remove unused log buffers from test cluster, fixes race ([#1612](https://github.com/pilosa/pilosa/pull/1612))
- Add --field-keys and --index-keys options to pilosa import ([#1621](https://github.com/pilosa/pilosa/pull/1621))
- Use passed stdin, stdout, and stderr in the cmd package ([#1620](https://github.com/pilosa/pilosa/pull/1620))
- Update Go client sample to match latest master ([#1614](https://github.com/pilosa/pilosa/pull/1614))
## [1.1.0] - 2018-08-21
This version contains 32 contributions from 5 contributors. There are 89 files changed; 2,752 insertions; and 1,013 deletions.
### Added
- Add CircleCI ([#1610](https://github.com/pilosa/pilosa/pull/1610))
- Add key translation to exports ([#1608](https://github.com/pilosa/pilosa/pull/1608))
- Support importing key values ([#1599](https://github.com/pilosa/pilosa/pull/1599), [#1601](https://github.com/pilosa/pilosa/pull/1601))
- Treat coordinator as primary translate store ([#1582](https://github.com/pilosa/pilosa/pull/1582))
- Add DEGRADED cluster state and handle gossip NodeLeave events correctly ([#1584](https://github.com/pilosa/pilosa/pull/1584))
- Add linters to gometalinter and fix related issues ([#1544](https://github.com/pilosa/pilosa/pull/1544), [#1543](https://github.com/pilosa/pilosa/pull/1543), [#1540](https://github.com/pilosa/pilosa/pull/1540), [#1539](https://github.com/pilosa/pilosa/pull/1539), [#1537](https://github.com/pilosa/pilosa/pull/1537), [#1536](https://github.com/pilosa/pilosa/pull/1536), [#1535](https://github.com/pilosa/pilosa/pull/1535), [#1534](https://github.com/pilosa/pilosa/pull/1534), [#1530](https://github.com/pilosa/pilosa/pull/1530), [#1529](https://github.com/pilosa/pilosa/pull/1529), [#1528](https://github.com/pilosa/pilosa/pull/1528), [#1526](https://github.com/pilosa/pilosa/pull/1526), [#1527](https://github.com/pilosa/pilosa/pull/1527))
- Add mutex field type ([#1524](https://github.com/pilosa/pilosa/pull/1524))
- Fragment rows() and rowsForColumn() ([#1532](https://github.com/pilosa/pilosa/pull/1532))
### Fixed
- Fix race on replicationClosing channel ([#1607](https://github.com/pilosa/pilosa/pull/1607))
- Prevent anti-entropy and cluster resize from running simultaneously ([#1586](https://github.com/pilosa/pilosa/pull/1586))
- Require a valid port that isn't greater than 65,535 ([#1603](https://github.com/pilosa/pilosa/pull/1603))
- Add view parameter to sync logic for syncing time fields ([#1602](https://github.com/pilosa/pilosa/pull/1602))
- Fix translator in cluster environment ([#1552](https://github.com/pilosa/pilosa/pull/1552))
- Use string prefix instead of equality so json error message will pass on all Go versions ([#1558](https://github.com/pilosa/pilosa/pull/1558))
## [1.0.2] - 2018-08-01
This version contains 11 contributions from 3 contributors. There are 30 files changed; 1,569 insertions; and 1,215 deletions.
### Fixed
- Fix documentation ([#1503](https://github.com/pilosa/pilosa/pull/1503), [#1495](https://github.com/pilosa/pilosa/pull/1495), [#1551](https://github.com/pilosa/pilosa/pull/1551))
- Fix places where empty IndexOptions were being used ([#1547](https://github.com/pilosa/pilosa/pull/1547))
- Fix translator syncing bug in cluster environments ([#1552](https://github.com/pilosa/pilosa/pull/1552))
- Fix race condition in translate_test ([#1541](https://github.com/pilosa/pilosa/pull/1541))
- Add IndexOptions to IndexInfo json response ([#1542](https://github.com/pilosa/pilosa/pull/1542))
- Add proper locking to cluster code to prevent races ([#1533](https://github.com/pilosa/pilosa/pull/1533))
- Re-export erroneously unexported func Row.Intersect ([#1502](https://github.com/pilosa/pilosa/pull/1502))
- Update parser to handle row keys on SetRowAttrs() ([#1555](https://github.com/pilosa/pilosa/pull/1555))
## [1.0.1] - 2018-07-11
This version contains 12 contributions from 4 contributors. There are 11 files changed; 133 insertions; and 39 deletions.
### Fixed
- Use `dep ensure -vendor-only` for build repeatability ([#1491](https://github.com/pilosa/pilosa/pull/1491))
- Make sure time range views are calculated correctly across months ([#1485](https://github.com/pilosa/pilosa/pull/1485))
- Fix up error handling, add a configurable timeout to http handler closing ([#1486](https://github.com/pilosa/pilosa/pull/1486))
- Add gossip Closer ([#1483](https://github.com/pilosa/pilosa/pull/1483))
- Update docs references to WebUI naming (console) and installation ([#1493](https://github.com/pilosa/pilosa/pull/1493))
## [1.0.0] - 2018-07-09
This version contains 218 contributions from 7 contributors. There are 184 files changed; 21,769 insertions; and 20,275 deletions.
### Added
- ID-Key Translation ([#1337](https://github.com/pilosa/pilosa/pull/1337))
- Add CORS support to handler ([#1327](https://github.com/pilosa/pilosa/pull/1327))
### Changed
- HTTP handler updates ([#1408](https://github.com/pilosa/pilosa/pull/1408), [#1399](https://github.com/pilosa/pilosa/pull/1399), [#1441](https://github.com/pilosa/pilosa/pull/1441), [#1375](https://github.com/pilosa/pilosa/pull/1375), [#1433](https://github.com/pilosa/pilosa/pull/1433), [#1444](https://github.com/pilosa/pilosa/pull/1444), [#1388](https://github.com/pilosa/pilosa/pull/1388), [#1309](https://github.com/pilosa/pilosa/pull/1309), [#1302](https://github.com/pilosa/pilosa/pull/1302), [#1304](https://github.com/pilosa/pilosa/pull/1304), [#1465](https://github.com/pilosa/pilosa/pull/1465), [#1466](https://github.com/pilosa/pilosa/pull/1466))
- Refactor/improve tests ([#1437](https://github.com/pilosa/pilosa/pull/1437), [#1434](https://github.com/pilosa/pilosa/pull/1434), [#1435](https://github.com/pilosa/pilosa/pull/1435), [#1425](https://github.com/pilosa/pilosa/pull/1425), [#1418](https://github.com/pilosa/pilosa/pull/1418), [#1419](https://github.com/pilosa/pilosa/pull/1419), [#1413](https://github.com/pilosa/pilosa/pull/1413), [#1394](https://github.com/pilosa/pilosa/pull/1394), [#1387](https://github.com/pilosa/pilosa/pull/1387), [#1386](https://github.com/pilosa/pilosa/pull/1386), [#1378](https://github.com/pilosa/pilosa/pull/1378), [#1364](https://github.com/pilosa/pilosa/pull/1364), [#1348](https://github.com/pilosa/pilosa/pull/1348), [#1340](https://github.com/pilosa/pilosa/pull/1340), [#1297](https://github.com/pilosa/pilosa/pull/1297))
- Simplify inter-node communication ([#1428](https://github.com/pilosa/pilosa/pull/1428), [#1427](https://github.com/pilosa/pilosa/pull/1427), [#1412](https://github.com/pilosa/pilosa/pull/1412), [#1398](https://github.com/pilosa/pilosa/pull/1398), [#1391](https://github.com/pilosa/pilosa/pull/1391), [#1389](https://github.com/pilosa/pilosa/pull/1389))
- Make gossip's interface to Pilosa the API struct ([#1452](https://github.com/pilosa/pilosa/pull/1452))
- Rename slice to shard ([#1426](https://github.com/pilosa/pilosa/pull/1426))
- Clearbit for time fields ([#1424](https://github.com/pilosa/pilosa/pull/1424))
- Update docs ([#1390](https://github.com/pilosa/pilosa/pull/1390), [#1329](https://github.com/pilosa/pilosa/pull/1329), [#1305](https://github.com/pilosa/pilosa/pull/1305), [#1296](https://github.com/pilosa/pilosa/pull/1296), [#1461](https://github.com/pilosa/pilosa/pull/1461))
- Simplify server setup ([#1417](https://github.com/pilosa/pilosa/pull/1417), [#1393](https://github.com/pilosa/pilosa/pull/1393),[#1451](https://github.com/pilosa/pilosa/pull/1451))
- Refactor API ([#1407](https://github.com/pilosa/pilosa/pull/1407))
- Rewrite PQL parser and add various improvements/simplifications ([#1382](https://github.com/pilosa/pilosa/pull/1382), [#1402](https://github.com/pilosa/pilosa/pull/1402), [#1354](https://github.com/pilosa/pilosa/pull/1354), [#1463](https://github.com/pilosa/pilosa/pull/1463))
- Rename "frame" to "field" ([#1395](https://github.com/pilosa/pilosa/pull/1395), [#1362](https://github.com/pilosa/pilosa/pull/1362), [#1360](https://github.com/pilosa/pilosa/pull/1360), [#1358](https://github.com/pilosa/pilosa/pull/1358), [#1357](https://github.com/pilosa/pilosa/pull/1357), [#1355](https://github.com/pilosa/pilosa/pull/1355))
- Optimize count ([#1365](https://github.com/pilosa/pilosa/pull/1365))
- Simplify bitmap max function ([#1333](https://github.com/pilosa/pilosa/pull/1333))
- Rename "bit" to "column" for clarity ([#1326](https://github.com/pilosa/pilosa/pull/1326))
- Rename pilosa.Bitmap to Row ([#1311](https://github.com/pilosa/pilosa/pull/1311))
- Invert encoding/decoding and remove internal references ([#1454](https://github.com/pilosa/pilosa/pull/1454))
### Removed
- Rename (unexport) many items to reduce public API footprint prior to 1.0 release ([#1470](https://github.com/pilosa/pilosa/pull/1470), [#1458](https://github.com/pilosa/pilosa/pull/1458), [#1450](https://github.com/pilosa/pilosa/pull/1450), [#1449](https://github.com/pilosa/pilosa/pull/1449), [#1448](https://github.com/pilosa/pilosa/pull/1448), [#1447](https://github.com/pilosa/pilosa/pull/1447), [#1446](https://github.com/pilosa/pilosa/pull/1446), [#1438](https://github.com/pilosa/pilosa/pull/1438), [#1443](https://github.com/pilosa/pilosa/pull/1443), [#1440](https://github.com/pilosa/pilosa/pull/1440), [#1439](https://github.com/pilosa/pilosa/pull/1439), [#1409](https://github.com/pilosa/pilosa/pull/1409), [#1392](https://github.com/pilosa/pilosa/pull/1392), [#1374](https://github.com/pilosa/pilosa/pull/1374), [#1372](https://github.com/pilosa/pilosa/pull/1372), [#1369](https://github.com/pilosa/pilosa/pull/1369), [#1367](https://github.com/pilosa/pilosa/pull/1367), [#1366](https://github.com/pilosa/pilosa/pull/1366), [#1351](https://github.com/pilosa/pilosa/pull/1351), [#1420](https://github.com/pilosa/pilosa/pull/1420), [#1416](https://github.com/pilosa/pilosa/pull/1416), [#1397](https://github.com/pilosa/pilosa/pull/1397))
- Remove dead code ([#1432](https://github.com/pilosa/pilosa/pull/1432), [#1457](https://github.com/pilosa/pilosa/pull/1457), [#1421](https://github.com/pilosa/pilosa/pull/1421), [#1411](https://github.com/pilosa/pilosa/pull/1411), [#1377](https://github.com/pilosa/pilosa/pull/1377), [#1393](https://github.com/pilosa/pilosa/pull/1393), [#1462](https://github.com/pilosa/pilosa/pull/1462))
- Remove view argument from Field.SetBit and Field.ClearBit ([#1396](https://github.com/pilosa/pilosa/pull/1396))
- Remove WebUI (now contained in a separate package) ([#1363](https://github.com/pilosa/pilosa/pull/1363))
- Remove bench command ([#1347](https://github.com/pilosa/pilosa/pull/1347))
- Remove "view" from API, handler, docs ([#1346](https://github.com/pilosa/pilosa/pull/1346))
- Remove backup/restore stuff ([#1339](https://github.com/pilosa/pilosa/pull/1339), [#1341](https://github.com/pilosa/pilosa/pull/1341))
- Remove inverse frame functionality ([#1335](https://github.com/pilosa/pilosa/pull/1335))
- Remove rangeEnabled option ([#1332](https://github.com/pilosa/pilosa/pull/1332))
- Remove index and field MarshalJSON ([#1468](https://github.com/pilosa/pilosa/pull/1468))
### Fixed
- Fix a few data races ([#1423](https://github.com/pilosa/pilosa/pull/1423))
- Fix for crash while removing containers ([#1401](https://github.com/pilosa/pilosa/pull/1401))
- Allow dashes in frame names ([#1415](https://github.com/pilosa/pilosa/pull/1415))
- Fix generate-config command, use single toml lib ([#1350](https://github.com/pilosa/pilosa/pull/1350))
## [0.10.0] - 2018-05-15
This version contains 93 contributions from 8 contributors. There are 93 files changed; 4,495 insertions; and 5,392 deletions.
### Added
- Add B+Tree containers (Enterprise Edition) ([#1285](https://github.com/pilosa/pilosa/pull/1285))
- Add /info endpoint ([#1236](https://github.com/pilosa/pilosa/pull/1236))
### Changed
- Wrap errors ([#1271](https://github.com/pilosa/pilosa/pull/1271), [#1258](https://github.com/pilosa/pilosa/pull/1258), [#1274](https://github.com/pilosa/pilosa/pull/1274), [#1270](https://github.com/pilosa/pilosa/pull/1270), [#1273](https://github.com/pilosa/pilosa/pull/1273), [#1272](https://github.com/pilosa/pilosa/pull/1272), [#1260](https://github.com/pilosa/pilosa/pull/1260), [#1259](https://github.com/pilosa/pilosa/pull/1259), [#1256](https://github.com/pilosa/pilosa/pull/1256), [#1257](https://github.com/pilosa/pilosa/pull/1257), [#1261](https://github.com/pilosa/pilosa/pull/1261), [#1262](https://github.com/pilosa/pilosa/pull/1262), [#1263](https://github.com/pilosa/pilosa/pull/1263), [#1265](https://github.com/pilosa/pilosa/pull/1265))
### Removed
- Remove unused code ([#1286](https://github.com/pilosa/pilosa/pull/1286))
- Remove input definition, add install-stringer to Makefile ([#1284](https://github.com/pilosa/pilosa/pull/1284))
- Remove /id and /hosts endpoints. Add local ID to /status ([#1238](https://github.com/pilosa/pilosa/pull/1238))
- Remove API.URI ([#1255](https://github.com/pilosa/pilosa/pull/1255))
### Fixed
- Assorted docs fixes ([#1281](https://github.com/pilosa/pilosa/pull/1281), [#1269](https://github.com/pilosa/pilosa/pull/1269))
- Update PQL syntax in bench subcommand ([#1279](https://github.com/pilosa/pilosa/pull/1279))
- Update help menu in WebUI ([#1278](https://github.com/pilosa/pilosa/pull/1278))
- Fix dead lock ([#1268](https://github.com/pilosa/pilosa/pull/1268))
- Make sure gossipMemberSet.Logger is set during server setup ([#1266](https://github.com/pilosa/pilosa/pull/1266))
- Make sure ~ is expanded in NewServer; BroadcastReceiver uses temp path ([#1242](https://github.com/pilosa/pilosa/pull/1242))
- Avoid creating a slice of nil timestamps on Import() ([#1234](https://github.com/pilosa/pilosa/pull/1234))
- Fixup internal client ([#1253](https://github.com/pilosa/pilosa/pull/1253))
## [0.9.0] - 2018-05-04
This version contains 188 contributions from 12 contributors. There are 141 files changed; 17,832 insertions; and 7,503 deletions.
*Please see special [upgrading instructions](https://www.pilosa.com/docs/latest/administration/#version-0-9) for this release.*
### Added
- Add ability to dynamically resize clusters ([#982](https://github.com/pilosa/pilosa/pull/982), [#946](https://github.com/pilosa/pilosa/pull/946), [#929](https://github.com/pilosa/pilosa/pull/929), [#927](https://github.com/pilosa/pilosa/pull/927), [#917](https://github.com/pilosa/pilosa/pull/917), [#913](https://github.com/pilosa/pilosa/pull/913), [#912](https://github.com/pilosa/pilosa/pull/912), [#908](https://github.com/pilosa/pilosa/pull/908))
- Update docs to include cluster-resize config and instructions ([#1088](https://github.com/pilosa/pilosa/pull/1088))
- Add support for lists of gossip seeds for redundancy ([#1133](https://github.com/pilosa/pilosa/pull/1133))
- Add HTTP Handler validation ([#1140](https://github.com/pilosa/pilosa/pull/1140), [#1121](https://github.com/pilosa/pilosa/pull/1121))
- Add validation around node-remove conditions ([#1138](https://github.com/pilosa/pilosa/pull/1138))
- broadcast.SendSync field creation and deletion to all nodes ([#1132](https://github.com/pilosa/pilosa/pull/1132))
- Spread recalculate caches to all nodes. Fixes #1069 ([#1109](https://github.com/pilosa/pilosa/pull/1109))
- Add QueryResult.Type to protobuf message to distiguish results at the client ([#1064](https://github.com/pilosa/pilosa/pull/1064))
- Modify `pilosa import` to support string rows/columns ([#1063](https://github.com/pilosa/pilosa/pull/1063))
- Add some statsd calls to HolderSyncer ([#1048](https://github.com/pilosa/pilosa/pull/1048))
- Add support for memberlist gossip configuration via pilosa.Config ([#1014](https://github.com/pilosa/pilosa/pull/1014))
- Add local and cluster IDs ([#1013](https://github.com/pilosa/pilosa/pull/1013), [#1245](https://github.com/pilosa/pilosa/pull/1245))
- Add HolderCleaner and view.DeleteFragment ([#985](https://github.com/pilosa/pilosa/pull/985))
- Add set-coordinator endpoint ([#963](https://github.com/pilosa/pilosa/pull/963))
- Implement Min/Max BSI queries ([#1191](https://github.com/pilosa/pilosa/pull/1191))
- Log time/version to startup log ([#1246](https://github.com/pilosa/pilosa/pull/1246))
- Documentation improvements ([#1135](https://github.com/pilosa/pilosa/pull/1135), [#1154](https://github.com/pilosa/pilosa/pull/1154), [#1091](https://github.com/pilosa/pilosa/pull/1091), [#1108](https://github.com/pilosa/pilosa/pull/1108), [#1087](https://github.com/pilosa/pilosa/pull/1087), [#1086](https://github.com/pilosa/pilosa/pull/1086), [#1026](https://github.com/pilosa/pilosa/pull/1026), [#1022](https://github.com/pilosa/pilosa/pull/1022), [#1007](https://github.com/pilosa/pilosa/pull/1007), [#981](https://github.com/pilosa/pilosa/pull/981), [#901](https://github.com/pilosa/pilosa/pull/901), [#972](https://github.com/pilosa/pilosa/pull/972), [#1215](https://github.com/pilosa/pilosa/pull/1215), [#1213](https://github.com/pilosa/pilosa/pull/1213), [#1224](https://github.com/pilosa/pilosa/pull/1224), [#1250](https://github.com/pilosa/pilosa/pull/1250))
### Changed
- Put Statik behind an interface ([#1163](https://github.com/pilosa/pilosa/pull/1163))
- Refactor diagnostics, inject gopsutil dependency ([#1166](https://github.com/pilosa/pilosa/pull/1166))
- Use boolean instead of address to configure coordinator ([#1158](https://github.com/pilosa/pilosa/pull/1158))
- Put GCNotify behind an interface ([#1148](https://github.com/pilosa/pilosa/pull/1148))
- Replace custom assembly bit functions with standard go ([#797](https://github.com/pilosa/pilosa/pull/797))
- Improve roaring tests ([#1115](https://github.com/pilosa/pilosa/pull/1115))
- Change configuration cluster.type (string) to cluster.disabled (bool) ([#1099](https://github.com/pilosa/pilosa/pull/1099))
- Use NodeID instead of URI for node identification ([#1077](https://github.com/pilosa/pilosa/pull/1077))
- Change gossip config from DefaultLocalConfig to DefaultWANConfig ([#1032](https://github.com/pilosa/pilosa/pull/1032))
- Use binary search in runAdd ([#1027](https://github.com/pilosa/pilosa/pull/1027))
- Use HTTP handler for gossip SendSync ([#1001](https://github.com/pilosa/pilosa/pull/1001))
- Group the write operations in syncBlock by MaxWritesPerRequest ([#950](https://github.com/pilosa/pilosa/pull/950))
- Refactor HTTPClient handling ([#991](https://github.com/pilosa/pilosa/pull/991))
- Remove FrameSchema. Move Fields to the Frame struct ([#907](https://github.com/pilosa/pilosa/pull/907))
- Refactor pilosa/server ([#1220](https://github.com/pilosa/pilosa/pull/1220))
- Clean up flipBitmap and add tests ([#1223](https://github.com/pilosa/pilosa/pull/1223))
- Move pilosa.Config to pilosa/server.Config ([#1216](https://github.com/pilosa/pilosa/pull/1216))
- Vendor github.com/golang/groupcache/lru ([#1221](https://github.com/pilosa/pilosa/pull/1221))
### Removed
- Remove the Gossip stutter from memberlist-related config options ([#1171](https://github.com/pilosa/pilosa/pull/1171))
- Remove old GossipPort and GossipSeed config options ([#1142](https://github.com/pilosa/pilosa/pull/1142))
- Remove cluster type `http` from docs ([#1130](https://github.com/pilosa/pilosa/pull/1130))
- Remove holder.Peek, combine with HasData, move server logic ([#1226](https://github.com/pilosa/pilosa/pull/1226))
- Remove PATCH frame endpoint ([#1222](https://github.com/pilosa/pilosa/pull/1222))
- Remove Index.MergeSchemas() method ([#1219](https://github.com/pilosa/pilosa/pull/1219))
- Remove references to Input Definition from the docs ([#1212](https://github.com/pilosa/pilosa/pull/1212))
- Remove Index.TimeQuantum ([#1209](https://github.com/pilosa/pilosa/pull/1209))
- Remove SecurityManager. Implement api restrictions in api package. ([#1207](https://github.com/pilosa/pilosa/pull/1207))
### Fixed
- Handle the scheme correctly in config.Bind ([#1143](https://github.com/pilosa/pilosa/pull/1143))
- Prevent excessive sendSync (createView) messages. ([#1139](https://github.com/pilosa/pilosa/pull/1139))
- Fix a shift logic bug in bitmapZeroRange ([#1110](https://github.com/pilosa/pilosa/pull/1110))
- Fix node id validation on set-coordinator ([#1102](https://github.com/pilosa/pilosa/pull/1102))
- Avoid overflow bug in differenceRunArray ([#1105](https://github.com/pilosa/pilosa/pull/1105))
- Fix bug in NewServerCluster where each host was its own coordinator ([#1101](https://github.com/pilosa/pilosa/pull/1101))
- Fix count/bitmap mismatch bug ([#1084](https://github.com/pilosa/pilosa/pull/1084))
- Fix edge case with Range() calls outside field Min/Max. Fixes #876. ([#979](https://github.com/pilosa/pilosa/pull/979))
- Bind the handler to all interfaces (0.0.0.0) in Dockerfile. Fixes #977. ([#980](https://github.com/pilosa/pilosa/pull/980))
- Fix nil client bug in monitorAntiEntropy (and test) ([#1233](https://github.com/pilosa/pilosa/pull/1233))
- Fix crash due to server.diagnostics.server not set ([#1229](https://github.com/pilosa/pilosa/pull/1229))
- Fix some cluster race conditions ([#1228](https://github.com/pilosa/pilosa/pull/1228))
### Deprecated
- Deprecate RangeEnabled option ([#1205](https://github.com/pilosa/pilosa/pull/1205))
### Performance
- Add benchmark for various container usage patterns ([#1017](https://github.com/pilosa/pilosa/pull/1017))
## [0.8.8] - 2018-02-19
This version contains 1 contribution from 2 contributors. There are 4 files changed; 1,153 insertions; and 618 deletions.
### Fixed
- Bug fixes and improved test coverage in roaring ([#1118](https://github.com/pilosa/pilosa/pull/1118))
## [0.8.7] - 2018-02-12
This version contains 1 contribution from 1 contributors. There are 2 files changed; 84 insertions; and 4 deletions.
### Fixed
- Fix a shift logic bug in bitmapZeroRange ([#1111](https://github.com/pilosa/pilosa/pull/1111))
## [0.8.6] - 2018-02-09
This version contains 2 contributions from 2 contributors. There are 3 files changed; 171 insertions; and 6 deletions.
### Fixed
- Fix overflow bug in differenceRunArray [#1106](https://github.com/pilosa/pilosa/pull/1106)
- Fix bug where count and bitmap queries could return different numbers [#1083](https://github.com/pilosa/pilosa/pull/1083)
## [0.8.5] - 2018-01-18
This version contains 1 contribution from 1 contributor. There is 1 file changed; 1 insertion, and 0 deletions.
### Fixed
- Bind Docker container on all interfaces ([#1061](https://github.com/pilosa/pilosa/pull/1061))
## [0.8.4] - 2018-01-10
This version contains 4 contributions from 3 contributors. There are 17 files changed; 974 insertions; and 221 deletions.
### Fixed
- Group the write operations in syncBlock by MaxWritesPerRequest ([#1038](https://github.com/pilosa/pilosa/pull/1038))
- Change gossip config from memberlist.DefaultLocalConfig to memberlist.DefaultWANConfig ([#1033](https://github.com/pilosa/pilosa/pull/1033))
### Performance
- Change AttrBlock handler calls to support protobuf instead of json ([#1046](https://github.com/pilosa/pilosa/pull/1046))
- Use RLock instead of Lock in a few places ([#1042](https://github.com/pilosa/pilosa/pull/1042))
## [0.8.3] - 2017-12-12
This version contains 1 contribution from 1 contributor. There are 2 files changed; 59 insertions; and 42 deletions.
### Fixed
- Protect against accessing pointers to memory which was unmapped ([#1000](https://github.com/pilosa/pilosa/pull/1000))
## [0.8.2] - 2017-12-05
This version contains 1 contribution from 1 contributor. There are 15 files changed; 127 insertions; and 98 deletions.
### Fixed
- Modify initialization of HTTP client so only one instance is created ([#994](https://github.com/pilosa/pilosa/pull/994))
## [0.8.1] - 2017-11-15
This version contains 2 contributions from 2 contributors. There are 4 files changed; 27 insertions; and 14 deletions.
### Fixed
- Fix CountOpenFiles() fatal crash ([#969](https://github.com/pilosa/pilosa/pull/969))
- Fix version check when local is greater than pilosa.com ([#968](https://github.com/pilosa/pilosa/pull/968))
## [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/v1.2...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
[0.9.0]: https://github.com/pilosa/pilosa/compare/v0.8...v0.9
[0.10.0]: https://github.com/pilosa/pilosa/compare/v0.9...v0.10
[1.0.0]: https://github.com/pilosa/pilosa/compare/v0.10...v1.0
[1.1.0]: https://github.com/pilosa/pilosa/compare/v1.0...v1.1
[1.2.0]: https://github.com/pilosa/pilosa/compare/v1.1...v1.2

View file

@ -1,177 +0,0 @@
# Contributing to Pilosa
The workflow components of these instructions apply to all Pilosa repositories.
## 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, organized with [Zenhub](https://www.zenhub.com/), which is publicly available as a browser extension. New features typically go through a [Proposal Process][4]
which starts by [opening a new issue][1] that describes the new feature proposal.
## Making code contributions
Before you start working on new features, you should [open a new issue][1] to let others know what
you're doing, 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].
### Development Environment
- Ensure you have a recent version of [Go](https://golang.org/doc/install) installed. Pilosa generally supports the current and previous minor versions; check our [CircleCI config file](../master/.circleci/config.yml) for the most up-to-date information.
- Make sure `$GOPATH` environment variable points to your Go working directory and `$PATH` incudes `$GOPATH/bin`, as described [here](https://golang.org/doc/code.html#GOPATH).
- Fork the [Pilosa repository][2] to your own account.
- It will be easier to follow these instructions if you:
```sh
export GH_USERNAME=<your github username>
```
- Create a directory (note that we use `github.com/pilosa`, NOT `github.com/USER`) and clone Pilosa:
```sh
mkdir -p ${GOPATH}/src/github.com/pilosa && cd $_
git clone https://github.com/pilosa/pilosa.git
```
- `cd` to your pilosa directory:
```sh
cd ${GOPATH}/src/github.com/pilosa/pilosa
```
- Install Pilosa command line tools:
```sh
make install
```
Running `pilosa` should now run a Pilosa instance.
- The official Pilosa repository is your "origin" remote in git. Add your fork as your github username
```sh
cd ${GOPATH}/src/github.com/pilosa/pilosa
git remote add ${GH_USERNAME} git@github.com:${GH_USERNAME}/pilosa.git
```
### Makefile
Pilosa includes a Makefile that automates several tasks:
- Install Pilosa:
```sh
make install
```
- Install build dependencies:
```sh
make install-build-deps
```
- Create the vendor directory:
```sh
make vendor
```
- Run the test suite:
```sh
make test
```
- View the coverage report:
```sh
make cover-viz
```
- Clear the `vendor/` and `build/` directories:
```sh
make clean
```
- Create release tarballs:
```sh
make release
```
- Regenerate protocol buffer files in `internal/`:
```sh
make generate-protoc
```
- Create tagged Docker image:
```sh
make docker
```
- Run tests inside Docker container:
```sh
make docker-test
```
Additional commands are available in the `Makefile`.
### Submitting code changes
- Before starting to work on a task, sync your branch with the upstream:
```sh
git checkout master
git pull
```
- Create a local feature branch:
```sh
git checkout -b something-amazing
```
- Commit your changes locally using `git add` and `git commit`. Please use [appropriate commit messages](https://chris.beams.io/posts/git-commit/).
- Make sure that you've written tests for your new feature, and then run the tests:
```sh
make test
```
- Verify that your pull request is applied to the latest version of code on github:
```sh
git checkout master
git pull
git checkout something-amazing
git rebase master
```
- Push to your fork:
```sh
git push -u $GH_USERNAME something-amazing: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,22 +1,55 @@
FROM golang:1.13.0 as builder
ARG GO_VERSION=latest
COPY . pilosa
#######################
### Lattice builder ###
#######################
RUN cd pilosa && CGO_ENABLED=0 make install FLAGS="-a"
FROM moleculacorp/nodejs:latest as lattice-builder
WORKDIR /lattice
FROM alpine:3.9.4
COPY lattice/package.json ./
COPY lattice/yarn.lock ./
RUN yarn install
LABEL maintainer "dev@pilosa.com"
COPY lattice ./
RUN yarn build
######################
### Pilosa builder ###
######################
FROM golang:${GO_VERSION} as pilosa-builder
ARG MAKE_FLAGS
WORKDIR /pilosa
RUN go get github.com/rakyll/statik
COPY . ./
COPY --from=lattice-builder /lattice/build /lattice
RUN /go/bin/statik -src=/lattice -dest=/pilosa
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
COPY --from=builder /go/bin/pilosa /pilosa
COPY --from=pilosa-builder /pilosa/build/featurebase /
COPY LICENSE /LICENSE
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"]

View file

@ -1,29 +1,35 @@
# 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.11
FROM golang:1.16
LABEL maintainer "dev@pilosa.com"
COPY . /go/src/github.com/pilosa/pilosa/
COPY . /go/src/github.com/molecula/featurebase/
RUN cd /go/src/github.com/pilosa/pilosa \
&& GO111MODULE=on make vendor
RUN cd /go/src/github.com/pilosa/pilosa \
&& CGO_ENABLED=0 make install FLAGS="-a"
# 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
RUN cp /go/bin/pilosa /pilosa
# 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
# 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 cd /go/src/github.com/molecula/featurebase/cmd/featurebase && \
go test -covermode=atomic -coverpkg=../../... -c -tags testrunmain -o featurebase && \
cp /go/src/github.com/molecula/featurebase/cmd/featurebase/featurebase /featurebase
COPY LICENSE /LICENSE
COPY NOTICE /NOTICE
EXPOSE 10101
VOLUME /data
ENTRYPOINT ["bash", "-c"]
CMD ["/pilosa", "server", "--data-dir", "/data", "--bind", "http://0.0.0.0:10101"]
CMD ["/featurebase", "-test.run=TestRunMain", "-test.coverprofile=/results/coverage.out", "server", "--data-dir", "/data", "--bind", "http://0.0.0.0:10101"]

View file

@ -0,0 +1,35 @@
# 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.16
LABEL maintainer "dev@pilosa.com"
COPY . /go/src/github.com/molecula/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
RUN cd /go/src/github.com/molecula/featurebase/cmd/featurebase && \
go test -covermode=atomic -coverpkg=../../... -c -tags testrunmain -o featurebase && \
cp /go/src/github.com/molecula/featurebase/cmd/featurebase/featurebase /featurebase
COPY NOTICE /NOTICE
COPY ./internal/clustertests /go/src/github.com/molecula/featurebase/internal/clustertests
EXPOSE 10101
VOLUME /data
ENTRYPOINT ["bash", "-c"]
CMD ["/featurebase", "-test.run=TestRunMain", "-test.coverprofile=/results/coverage.out", "server", "--data-dir", "/data", "--bind", "http://0.0.0.0:10101"]

202
LICENSE
View file

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

305
Makefile
View file

@ -1,23 +1,34 @@
.PHONY: build check-clean clean cover cover-viz default docker docker-build docker-test generate generate-protoc generate-pql gometalinter install install-build-deps install-golangci-lint install-gometalinter install-protoc install-protoc-gen-gofast install-peg prerelease prerelease-upload release release-build test
.PHONY: build check-clean clean build-lattice cover cover-viz default docker docker-build docker-test docker-tag-push generate generate-protoc generate-pql generate-statik gometalinter install install-build-deps install-golangci-lint install-gometalinter install-protoc install-protoc-gen-gofast install-peg install-statik release release-build test testv testv-race testvsub testvsub-race test-txstore-rbf
CLONE_URL=github.com/pilosa/pilosa
VERSION := $(shell git describe --tags 2> /dev/null || echo unknown)
VERSION_ID = $(if $(ENTERPRISE_ENABLED),enterprise-)$(VERSION)-$(GOOS)-$(GOARCH)
BRANCH := $(if $(TRAVIS_BRANCH),$(TRAVIS_BRANCH),$(if $(CIRCLE_BRANCH),$(CIRCLE_BRANCH),$(shell git rev-parse --abbrev-ref HEAD)))
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)
BRANCH := $(if $(CIRCLE_BRANCH),$(CIRCLE_BRANCH),$(shell git rev-parse --abbrev-ref HEAD))
BRANCH_ID := $(BRANCH)-$(GOOS)-$(GOARCH)
BUILD_TIME := $(shell date -u +%FT%T%z)
SHARD_WIDTH = 20
LDFLAGS="-X github.com/pilosa/pilosa/v2.Version=$(VERSION) -X github.com/pilosa/pilosa/v2.BuildTime=$(BUILD_TIME) -X github.com/pilosa/pilosa/v2.Enterprise=$(if $(ENTERPRISE_ENABLED),1)"
GO_VERSION=latest
ENTERPRISE ?= 0
ENTERPRISE_ENABLED = $(subst 0,,$(ENTERPRISE))
RELEASE ?= 0
RELEASE_ENABLED = $(subst 0,,$(RELEASE))
BUILD_TAGS += $(if $(ENTERPRISE_ENABLED),enterprise)
BUILD_TAGS += $(if $(RELEASE_ENABLED),release)
COMMIT := $(shell git describe --exact-match >/dev/null 2>&1 || git rev-parse --short HEAD)
LDFLAGS="-X github.com/molecula/featurebase/v3.Version=$(VERSION) -X github.com/molecula/featurebase/v3.BuildTime=$(BUILD_TIME) -X github.com/molecula/featurebase/v3.Variant=$(VARIANT) -X github.com/molecula/featurebase/v3.Commit=$(COMMIT) -X github.com/molecula/featurebase/v3.TrialDeadline=$(TRIAL_DEADLINE)"
GO_VERSION=1.16.10
DOCKER_BUILD= # set to 1 to use `docker-build` instead of `build` when creating a release
BUILD_TAGS += shardwidth$(SHARD_WIDTH)
LICENSE_HASH=$(shell head -13 pilosa.go | shasum | cut -f 1 -d " ")
TEST_TAGS = roaringparanoia
UNAME := $(shell uname -s)
TEST_TIMEOUT=30m
RACE_TEST_TIMEOUT=90m
ifeq ($(UNAME), Darwin)
IS_MACOS:=1
else
IS_MACOS:=0
endif
export GO111MODULE=on
export GOPRIVATE=github.com/molecula
export CGO_ENABLED=0
# Run tests and compile Pilosa
default: test build
@ -28,14 +39,48 @@ clean:
# Set up vendor directory using `go mod vendor`
vendor: go.mod
go mod vendor
$(GO) mod vendor
version:
@echo $(VERSION)
# Run test suite
test:
go test ./... -tags='$(BUILD_TAGS)' $(TESTFLAGS)
$(GO) test ./... -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -timeout $(TEST_TIMEOUT)
# Run test suite with race flag
test-race:
CGO_ENABLED=1 $(GO) test ./... -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -race -timeout $(RACE_TEST_TIMEOUT) -v
testv: topt testvsub
testv-race: topt-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 i in boltdb client ctl http pg pql rbf roaring server sql txkey; do \
echo; echo "___ testing subpkg $$i"; \
cd $$i; pwd; \
$(GO) test -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -timeout $(RACE_TEST_TIMEOUT) || break; \
echo; echo "999 done testing subpkg $$i"; \
cd ..; \
done
testvsub-race:
set -e; for i in boltdb client ctl http pg pql rbf roaring server sql txkey; do \
echo; echo "___ testing subpkg $$i -race"; \
cd $$i; pwd; \
CGO_ENABLED=1 $(GO) test -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -v -race -timeout $(RACE_TEST_TIMEOUT) || break; \
echo; echo "999 done testing subpkg $$i -race"; \
cd ..; \
done
bench:
go test ./... -bench=. -run=NoneZ -timeout=127m $(TESTFLAGS)
$(GO) test ./... -bench=. -run=NoneZ -timeout=127m $(TESTFLAGS)
# Run test suite with coverage enabled
cover:
@ -44,19 +89,27 @@ cover:
# Run test suite with coverage enabled and view coverage results in browser
cover-viz: cover
go tool cover -html=build/coverage.out
$(GO) tool cover -html=build/coverage.out
# Compile Pilosa
build:
go build -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/pilosa
$(GO) build -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/featurebase
# Create a single release build under the build directory
release-build:
$(MAKE) $(if $(DOCKER_BUILD),docker-)build FLAGS="-o build/pilosa-$(VERSION_ID)/pilosa" RELEASE=1
cp NOTICE README.md build/pilosa-$(VERSION_ID)
$(if $(ENTERPRISE_ENABLED),cp enterprise/COPYING build/pilosa-$(VERSION_ID),cp LICENSE build/pilosa-$(VERSION_ID))
tar -cvz -C build -f build/pilosa-$(VERSION_ID).tar.gz pilosa-$(VERSION_ID)/
@echo Created release build: build/pilosa-$(VERSION_ID).tar.gz
$(MAKE) $(if $(DOCKER_BUILD),docker-)build FLAGS="-o build/featurebase-$(VERSION_ID)/featurebase"
cp NOTICE install/featurebase.conf install/featurebase*.service build/featurebase-$(VERSION_ID)
tar -cvz -C build -f build/featurebase-$(VERSION_ID).tar.gz featurebase-$(VERSION_ID)/
@echo Created release build: build/featurebase-$(VERSION_ID).tar.gz
test-release-build: docker-build
mv build/featurebase-$(VERSION_ID).tar.gz install/
cd install && docker build -t featurebase:test_installation \
-f test_installation.Dockerfile \
--build-arg release_tarball=featurebase-$(VERSION_ID).tar.gz .
mv install/featurebase-$(VERSION_ID).tar.gz build/
docker run -it -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
featurebase:test_installation
# Error out if there are untracked changes in Git
check-clean:
@ -64,76 +117,174 @@ ifndef SKIP_CHECK_CLEAN
$(if $(shell git status --porcelain),$(error Git status is not clean! Please commit or checkout/reset changes.))
endif
# Create release build tarballs for all supported platforms. Linux compilation happens under Docker.
release: check-clean
# Create release build tarballs for all supported platforms. DEPRECATED: Use `docker-release`
release: check-clean generate-statik-docker
$(MAKE) release-build GOOS=darwin GOARCH=amd64
$(MAKE) release-build GOOS=darwin GOARCH=amd64 ENTERPRISE=1
$(MAKE) release-build GOOS=darwin GOARCH=arm64
$(MAKE) release-build GOOS=linux GOARCH=amd64
$(MAKE) release-build GOOS=linux GOARCH=amd64 ENTERPRISE=1
$(MAKE) release-build GOOS=linux GOARCH=386
$(MAKE) release-build GOOS=linux GOARCH=386 ENTERPRISE=1
$(MAKE) release-build GOOS=linux GOARCH=arm64
# Create release build tarballs for all supported platforms. Same as `release`, but without embedded Lattice UI.
release-sans-ui: check-clean
rm -f statik/statik.go
$(MAKE) release-build GOOS=darwin GOARCH=amd64
$(MAKE) release-build GOOS=darwin GOARCH=arm64
$(MAKE) release-build GOOS=linux GOARCH=amd64
$(MAKE) release-build GOOS=linux GOARCH=arm64
package:
go build -o featurebase ./cmd/featurebase
nfpm package --packager deb --target featurebase_$(VERSION_ID).deb
nfpm package --packager rpm --target featurebase_$(VERSION_ID).rpm
# try (e.g.) internal/clustertests/docker-compose-replication2.yml
DOCKER_COMPOSE=internal/clustertests/docker-compose.yml
# 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. This will catch changes to internal/clustertests/*.go, but if you
# make changes to Pilosa, you'll want to run clustertests-build to rebuild the
# pilosa image.
clustertests:
docker-compose -f $(DOCKER_COMPOSE) down
docker-compose -f $(DOCKER_COMPOSE) build client1
docker-compose -f $(DOCKER_COMPOSE) up --exit-code-from=client1
# 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
# Like clustertests, but rebuilds all images.
clustertests-build:
docker-compose -f $(DOCKER_COMPOSE) down
docker-compose -f $(DOCKER_COMPOSE) up --exit-code-from=client1 --build
# Create prerelease builds
prerelease:
$(MAKE) release-build GOOS=linux GOARCH=amd64 VERSION_ID=$$\(BRANCH_ID\)
$(if $(shell git describe --tags --exact-match HEAD),$(MAKE) release)
prerelease-upload:
aws s3 sync build/ s3://build.pilosa.com/ --exclude "*" --include "*.tar.gz" --acl public-read
# Run the cluster tests with authentication enabled
AUTH_ARGS="-c /go/src/github.com/molecula/featurebase/internal/clustertests/testdata/featurebase.conf"
authclustertests: vendor
$(eval PROJECT=authclustertests)
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 Pilosa
install:
go install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/pilosa
$(GO) install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/featurebase
install-bench:
$(GO) install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/pilosa-bench
# 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/pilosa/pilosa/v2/internal
$(GO) generate github.com/molecula/featurebase/v3/pb
# `go generate` statik assets (lattice UI)
generate-statik: build-lattice require-statik
$(GO) generate github.com/molecula/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/pilosa/pilosa/v2
$(GO) generate github.com/molecula/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
protoc -I proto proto/vdsm/vdsm.proto --go_out=plugins=grpc:proto
# TODO: Modify above commands and remove the below mv if possible.
# See https://go-review.googlesource.com/c/protobuf/+/219298/ for info on --go-opt
# I couldn't get it to work during development - Cody
cp -r proto/github.com/molecula/featurebase/v3/proto/ proto/
rm -rf proto/github.com
# `go generate` all needed packages
generate: generate-protoc generate-stringer generate-pql
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)" \
--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:
docker build -t "pilosa:$(VERSION)" .
@echo Created docker image: pilosa:$(VERSION)
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)
# Compile Pilosa inside Docker container
docker-build:
docker run --rm -v $(PWD):/go/src/$(CLONE_URL) -w /go/src/$(CLONE_URL) -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) golang:$(GO_VERSION) go build -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) $(CLONE_URL)/cmd/pilosa
# 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)
# Install diagnostic pilosa-keydump tool. Allows viewing the keys in a transaction-engine directory.
pilosa-keydump:
$(GO) install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/pilosa-keydump
# Install diagnostic pilosa-chk tool for string translations and fragment checksums.
pilosa-chk:
$(GO) install -tags='$(BUILD_TAGS)' -ldflags $(LDFLAGS) $(FLAGS) ./cmd/pilosa-chk
pilosa-fsck:
cd ./cmd/pilosa-fsck && make install && make release
# Run Pilosa tests inside Docker container
docker-test:
docker run --rm -v $(PWD):/go/src/$(CLONE_URL) -w /go/src/$(CLONE_URL) golang:$(GO_VERSION) go test -tags='$(BUILD_TAGS)' $(TESTFLAGS) ./...
docker run --rm -v $(PWD):/go/src/$(CLONE_URL) -w /go/src/$(CLONE_URL) golang:$(GO_VERSION) go test -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -timeout $(TEST_TIMEOUT) ./...
# Must use bash in order to -o pipefail; otherwise the tee will hide red tests.
# run top tests, not subdirs. print summary red/green after.
# The \-\-\- FAIL avoids counting the extra two FAIL strings at then bottom of log.topt.
topt:
mv log.topt.roar log.topt.roar.prev || true
$(eval SHELL:=/bin/bash) set -o pipefail; $(GO) test -v -timeout $(RACE_TEST_TIMEOUT) -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) 2>&1 | tee log.topt.roar
@echo " log.topt.roar green: \c"; cat log.topt.roar | grep PASS |wc -l
@echo " log.topt.roar red: \c"; cat log.topt.roar | grep '\-\-\- FAIL' | wc -l
topt-race:
mv log.topt.race log.topt.race.prev || true
$(eval SHELL:=/bin/bash) set -o pipefail; CGO_ENABLED=1 $(GO) test -race -timeout $(RACE_TEST_TIMEOUT) -v -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) 2>&1 | tee log.topt.race
@echo " log.topt.race green: \c"; cat log.topt.race | grep PASS |wc -l
@echo " log.topt.race red: \c"; cat log.topt.race | grep '\-\-\- FAIL' | wc -l
# Run golangci-lint
golangci-lint: require-golangci-lint
golangci-lint run
golangci-lint run --timeout 3m --skip-files '.*\.peg\.go'
# Alias
linter: golangci-lint
# Better alias
ocd: golangci-lint
# Run gometalinter with custom flags
gometalinter: require-gometalinter vendor
@ -158,13 +309,6 @@ gometalinter: require-gometalinter vendor
--exclude "^pql/pql.peg.go" \
./...
# Verify that all Go files have license header
check-license-headers: SHELL:=/bin/bash
check-license-headers:
@! find . -name '*.go' | grep -v '^./vendor' | while read fn;\
do [[ `head -13 $$fn | shasum | cut -f 1 -d " "` == $(LICENSE_HASH) ]] || echo $$fn; done | \
grep -v apimethod_string.go | grep -v pb.go | grep -v peg.go | grep -v lru.go | grep -v btree | grep -v enterprise
######################
# Build dependencies #
######################
@ -175,24 +319,33 @@ require-%:
$(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-stringer install-peg
install-build-deps: install-protoc-gen-gofast install-protoc install-statik install-stringer install-peg
install-statik:
go install github.com/rakyll/statik@latest
install-stringer:
GO111MODULE=off go get -u golang.org/x/tools/cmd/stringer
GO111MODULE=off $(GO) get -u golang.org/x/tools/cmd/stringer
install-protoc-gen-gofast:
GO111MODULE=off go get -u github.com/gogo/protobuf/protoc-gen-gofast
GO111MODULE=off $(GO) get -u github.com/gogo/protobuf/protoc-gen-gofast
install-protoc-gen-go:
GO111MODULE=off $(GO) get -u github.com/golang/protobuf/protoc-gen-go
install-protoc:
@echo This tool cannot automatically install protoc. Please download and install protoc from https://google.github.io/proto-lens/installing-protoc.html
install-peg:
GO111MODULE=off go get github.com/pointlander/peg
GO111MODULE=off $(GO) get github.com/pointlander/peg
install-golangci-lint:
GO111MODULE=off go get github.com/golangci/golangci-lint/cmd/golangci-lint
GO111MODULE=off $(GO) get github.com/golangci/golangci-lint/cmd/golangci-lint
install-gometalinter:
GO111MODULE=off go get -u github.com/alecthomas/gometalinter
GO111MODULE=off $(GO) get -u github.com/alecthomas/gometalinter
GO111MODULE=off gometalinter --install
GO111MODULE=off go get github.com/remyoudompheng/go-misc/deadcode
GO111MODULE=off $(GO) get github.com/remyoudompheng/go-misc/deadcode
test-external-lookup:
$(GO) test . -tags='$(BUILD_TAGS) $(TEST_TAGS)' $(TESTFLAGS) -run ^TestExternalLookup$$ -externalLookupDSN $(EXTERNAL_LOOKUP_DSN)

26
NOTES
View file

@ -1,26 +0,0 @@
Index Column
┌───────────▼────────────────────────────┐
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
Row──▶0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│────────────────────────────────────────┤
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│0000000000000000000000000000000000000000│
│────────────────────────────────────────┤
F ▶│0000000000000000000000000000000000000000│
i ││0000000000000000000000000000000000000000│
e ││0000000000000000000000000000000000000000│
l ││0000000000000000000000000000000000000000│
d ▶│0000000000000000000000000000000000000000│
└────────────────────────────────────────┘
▲───────────▲
Shard
Fragment=intersection of field & shard

60
NOTICE
View file

@ -1,44 +1,12 @@
Software license
================
Copyright (C) 2017-2018 Pilosa Corp. All rights reserved.
Licensed under the Apache License, Version 2.0 (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.
Enterprise Edition software license
===================================
Files contained under the directory `enterprise` are subject to the following
license notice (Full license included in the file `COPYING`):
Copyright (C) 2018 Pilosa Corp. All rights reserved.
Pilosa Enterprise Edition is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pilosa Enterprise Edition is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Pilosa Enterprise Edition. If not, see <http://www.gnu.org/licenses/>.
Copyright (C) 2017-2021 Molecula Corp. All rights reserved.
Third-party software licenses
=============================
The file /pilosa/lru/lru.go contains a redistribution of lru
The file /lru/lru.go contains a redistribution of lru
(github.com/golang/groupcache/lru); the license follows:
Copyright 2013 Google Inc.
@ -115,3 +83,27 @@ The file /server/tlsconfig.go contains a modified redistribution of bridge
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.

View file

@ -1,80 +1,6 @@
<p>
<a href="https://www.pilosa.com">
<img src="https://www.pilosa.com/img/logo.svg" width="50%">
</a>
</p>
# FeatureBase, a distributed bitmap index
[![CircleCI](https://circleci.com/gh/pilosa/pilosa/tree/master.svg?style=shield)](https://circleci.com/gh/pilosa/pilosa/tree/master)
[![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)
See our [internal documentation](https://internal-docs.molecula.cloud), which includes all [external documentation](https://docs.molecula.cloud), plus many internal-only pages, listed under the "Internal" heading in the main navigation bar.
## 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)
Follow along with the [Sample Project](https://internal-docs.molecula.cloud/tutorials/getting-started) to get a better understanding of FeatureBase's capabilities.
Want to contribute? One of the easiest ways is to [tell us how you're using (or want to use) Pilosa](https://github.com/pilosa/pilosa/issues/1074). We learn from every discussion!
## Docs
See our [Documentation](https://www.pilosa.com/docs/) for information about installing and working with Pilosa.
## Getting Started
1. [Install Pilosa](https://www.pilosa.com/docs/installation/).
2. [Start Pilosa](https://www.pilosa.com/docs/getting-started/#starting-pilosa) with the default configuration:
```shell
pilosa server
```
and verify that it's running:
```shell
curl localhost:10101/nodes
```
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
Check out how the Pilosa [Data Model](https://www.pilosa.com/docs/data-model/) works.
## Query Language
You can interact with Pilosa directly in the console using the [Pilosa Query Language](https://www.pilosa.com/docs/query-language/) (PQL).
## Client Libraries
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)
## Licenses
The core Pilosa code base and all default builds (referred to as Pilosa Community Edition) are licensed completely under the Apache License, Version 2.0.
If you build Pilosa with the `enterprise` build tag (Pilosa Enterprise Edition), then that build will include features licensed under the GNU Affero General
Public License (AGPL). Enterprise code is located entirely in the [github.com/pilosa/pilosa/enterprise](https://github.com/pilosa/pilosa/tree/master/enterprise)
directory. See [github.com/pilosa/pilosa/NOTICE](https://github.com/pilosa/pilosa/blob/master/NOTICE) and
[github.com/pilosa/pilosa/LICENSE](https://github.com/pilosa/pilosa/blob/master/LICENSE) for more information about Pilosa licenses.
## Get Support
There are [several channels](https://www.pilosa.com/community/#support) available for you to reach out to us for support.
## Contributing
Pilosa is an open source project. Please see our [Contributing Guide](CONTRIBUTING.md) for information about how to get involved.

2685
api.go

File diff suppressed because it is too large Load diff

202
api/client/grpc.go Normal file
View file

@ -0,0 +1,202 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
import (
"context"
"crypto/tls"
"sync"
"github.com/molecula/featurebase/v3/logger"
pb "github.com/molecula/featurebase/v3/proto"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
)
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.WithInsecure())
}
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
}

File diff suppressed because it is too large Load diff

View file

@ -19,25 +19,35 @@ func _() {
_ = x[apiFragmentBlockData-8]
_ = x[apiFragmentBlocks-9]
_ = x[apiFragmentData-10]
_ = x[apiField-11]
_ = x[apiFieldAttrDiff-12]
_ = x[apiImport-13]
_ = x[apiImportValue-14]
_ = x[apiIndex-15]
_ = x[apiIndexAttrDiff-16]
_ = 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[apiRemoveNode-19]
_ = x[apiResizeAbort-20]
_ = x[apiSetCoordinator-21]
_ = x[apiSchema-21]
_ = x[apiShardNodes-22]
_ = x[apiViews-23]
_ = x[apiApplySchema-24]
_ = x[apiState-23]
_ = x[apiViews-24]
_ = x[apiApplySchema-25]
_ = x[apiStartTransaction-26]
_ = x[apiFinishTransaction-27]
_ = x[apiTransactions-28]
_ = x[apiGetTransaction-29]
_ = x[apiActiveQueries-30]
_ = x[apiPastQueries-31]
_ = x[apiIDReserve-32]
_ = x[apiIDCommit-33]
_ = x[apiIDReset-34]
}
const _apiMethod_name = "apiClusterMessageapiCreateFieldapiCreateIndexapiDeleteFieldapiDeleteAvailableShardapiDeleteIndexapiDeleteViewapiExportCSVapiFragmentBlockDataapiFragmentBlocksapiFragmentDataapiFieldapiFieldAttrDiffapiImportapiImportValueapiIndexapiIndexAttrDiffapiQueryapiRecalculateCachesapiRemoveNodeapiResizeAbortapiSetCoordinatorapiShardNodesapiViewsapiApplySchema"
const _apiMethod_name = "apiClusterMessageapiCreateFieldapiCreateIndexapiDeleteFieldapiDeleteAvailableShardapiDeleteIndexapiDeleteViewapiExportCSVapiFragmentBlockDataapiFragmentBlocksapiFragmentDataapiTranslateDataapiFieldTranslateDataapiFieldapiImportapiImportValueapiIndexapiQueryapiRecalculateCachesapiRemoveNodeapiResizeAbortapiSchemaapiShardNodesapiStateapiViewsapiApplySchemaapiStartTransactionapiFinishTransactionapiTransactionsapiGetTransactionapiActiveQueriesapiPastQueriesapiIDReserveapiIDCommitapiIDReset"
var _apiMethod_index = [...]uint16{0, 17, 31, 45, 59, 82, 96, 109, 121, 141, 158, 173, 181, 197, 206, 220, 228, 244, 252, 272, 285, 299, 316, 329, 337, 351}
var _apiMethod_index = [...]uint16{0, 17, 31, 45, 59, 82, 96, 109, 121, 141, 158, 173, 189, 210, 218, 227, 241, 249, 257, 277, 290, 304, 313, 326, 334, 342, 356, 375, 395, 410, 427, 443, 457, 469, 480, 490}
func (i apiMethod) String() string {
if i < 0 || i >= apiMethod(len(_apiMethod_index)-1) {

205
attr.go
View file

@ -1,205 +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"
"sort"
"github.com/gogo/protobuf/proto"
"github.com/pilosa/pilosa/v2/internal"
)
// Attribute data type enum.
const (
attrTypeString = 1
attrTypeInt = 2
attrTypeBool = 3
attrTypeFloat = 4
)
// AttrStore represents an interface for handling row/column attributes.
type AttrStore interface {
Path() string
Open() error
Close() error
Attrs(id uint64) (m map[string]interface{}, err error)
SetAttrs(id uint64, m map[string]interface{}) error
SetBulkAttrs(m map[uint64]map[string]interface{}) error
Blocks() ([]AttrBlock, error)
BlockData(i uint64) (map[uint64]map[string]interface{}, error)
}
// nopStore represents an AttrStore that doesn't do anything.
var nopStore AttrStore = nopAttrStore{}
// newNopAttrStore returns an attr store which does nothing. It returns a global
// object to avoid unnecessary allocations.
func newNopAttrStore(string) AttrStore { return nopStore }
// nopAttrStore represents a no-op implementation of the AttrStore interface.
type nopAttrStore struct{}
// Path is a no-op implementation of AttrStore Path method.
func (s nopAttrStore) Path() string { return "" }
// Open is a no-op implementation of AttrStore Open method.
func (s nopAttrStore) Open() error { return nil }
// Close is a no-op implementation of AttrStore Close method.
func (s nopAttrStore) Close() error { return nil }
// Attrs is a no-op implementation of AttrStore Attrs method.
func (s nopAttrStore) Attrs(id uint64) (m map[string]interface{}, err error) { return nil, nil }
// SetAttrs is a no-op implementation of AttrStore SetAttrs method.
func (s nopAttrStore) SetAttrs(id uint64, m map[string]interface{}) error { return nil }
// SetBulkAttrs is a no-op implementation of AttrStore SetBulkAttrs method.
func (s nopAttrStore) SetBulkAttrs(m map[uint64]map[string]interface{}) error { return nil }
// Blocks is a no-op implementation of AttrStore Blocks method.
func (s nopAttrStore) Blocks() ([]AttrBlock, error) { return nil, nil }
// BlockData is a no-op implementation of AttrStore BlockData method.
func (s nopAttrStore) BlockData(i uint64) (map[uint64]map[string]interface{}, error) { return nil, nil }
// 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:]
}
}
}
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
}
// EncodeAttrs encodes an attribute map into a byte slice.
func EncodeAttrs(attr map[string]interface{}) ([]byte, error) {
return proto.Marshal(&internal.AttrMap{Attrs: encodeAttrs(attr)})
}
// DecodeAttrs decodes a byte slice into an attribute map.
func DecodeAttrs(v []byte) (map[string]interface{}, error) {
var pb internal.AttrMap
if err := proto.Unmarshal(v, &pb); err != nil {
return nil, err
}
return decodeAttrs(pb.GetAttrs()), nil
}

View file

@ -1,201 +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 (
"io/ioutil"
"os"
"reflect"
"runtime"
"sync"
"testing"
"github.com/pilosa/pilosa/v2"
"github.com/pilosa/pilosa/v2/boltdb"
)
// Ensure database can set and retrieve column attributes.
func TestAttrStore_Attrs(t *testing.T) {
s := 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 := 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 := 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 := 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])
}
}
// AttrStore represents a test wrapper for pilosa.AttrStore.
type AttrStore struct {
pilosa.AttrStore
}
// NewAttrStore returns a new instance of AttrStore.
func NewAttrStore(string) pilosa.AttrStore {
f, err := ioutil.TempFile("", "pilosa-attr-")
if err != nil {
panic(err)
}
f.Close()
os.Remove(f.Name())
return &AttrStore{boltdb.NewAttrStore(f.Name())}
}
func BenchmarkAttrStore_Duplicate(b *testing.B) {
s := MustOpenAttrStore()
defer s.Close()
// Set attributes.
const n = 5
for i := 0; i < n; i++ {
if err := s.SetAttrs(uint64(i), map[string]interface{}{"A": 100, "B": "foo", "C": true, "D": 100.2}); err != nil {
b.Fatal(err)
}
}
b.ReportAllocs()
b.ResetTimer()
// Update attributes with an existing subset.
cpuN := runtime.GOMAXPROCS(0)
var wg sync.WaitGroup
errchan := make(chan error)
for i := 0; i < cpuN; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < b.N/cpuN; j++ {
if err := s.SetAttrs(uint64(j%n), map[string]interface{}{"A": int64(100), "B": "foo", "D": 100.2}); err != nil {
errchan <- err
}
}
}()
}
go func() {
wg.Wait()
close(errchan)
}()
if err := <-errchan; err != nil {
b.Fatal(err)
}
}
// MustOpenAttrStore returns a new, opened attribute store at a temporary path. Panic on error.
func MustOpenAttrStore() pilosa.AttrStore {
s := NewAttrStore("")
if err := s.Open(); err != nil {
panic(err)
}
return s
}
// Close closes the database and removes the underlying data.
func (s *AttrStore) Close() error {
defer os.RemoveAll(s.Path())
return s.AttrStore.Close()
}

12
audit.go Normal file
View file

@ -0,0 +1,12 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"github.com/molecula/featurebase/v3/testhook"
)
var NewAuditor func() testhook.Auditor = NewNopAuditor
func NewNopAuditor() testhook.Auditor {
return testhook.NewNopAuditor()
}

39
audit_internal_test.go Normal file
View file

@ -0,0 +1,39 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"fmt"
"reflect"
"github.com/molecula/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{},
}
}

94
audit_test.go Normal file
View file

@ -0,0 +1,94 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa_test
import (
"fmt"
"os"
"reflect"
"github.com/molecula/featurebase/v3"
"github.com/molecula/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
}

307
authn/authenticate.go Normal file
View file

@ -0,0 +1,307 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// Package authn handles authentication
package authn
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/golang-jwt/jwt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/molecula/featurebase/v3/logger"
"github.com/pkg/errors"
"golang.org/x/oauth2"
)
// cachedGroups is used to hold groups and when they were last cached
type cachedGroups struct {
cacheTime time.Time
groups []Group
}
// cacheToken is used to hold tokens and when they were added to the cache
type cachedToken struct {
cacheTime time.Time
token *oauth2.Token
}
// 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"`
}
// 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 {
Groups []Group `json:"value"`
}
// Auth holds state, configuration, and utilities needed for authentication.
type Auth struct {
logger logger.Logger
cookieName 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
tokenTTR time.Duration // tokenTTR (time to refresh) is used to determine if a token should be refreshed or not
tokenCache map[string]cachedToken // tokenCache is a map of accessToken -> *oauth2.Token which we can use to refresh the tokens
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
}
// 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) (auth *Auth, err error) {
auth = &Auth{
logger: logger,
cookieName: "molecula-chip",
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,
},
},
tokenCache: map[string]cachedToken{},
groupsCache: map[string]cachedGroups{},
cacheTTL: 10 * time.Minute,
tokenTTR: 7 * time.Minute,
lastCacheClean: time.Now(),
}
if auth.secretKey, err = decodeHex(secretKey); err != nil {
return nil, errors.Wrap(err, "decoding secret key")
}
return auth, nil
}
// SecretKey is a convenient function to get the SecretKey from an Auth struct
func (a Auth) SecretKey() []byte {
return a.secretKey
}
// Authenticate takes in a bearer token `bearer` 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(ctx context.Context, bearer string) (*UserInfo, error) {
// clean up the cache every 30 minutes or so
if time.Now().Sub(a.lastCacheClean) >= 30*time.Minute {
a.cleanCache()
}
if tkn, ok := a.tokenCache[bearer]; ok && (tkn.token.Expiry.Sub(time.Now()) <= a.tokenTTR || !tkn.token.Valid()) {
// refresh the token
resp, err := http.PostForm(a.oAuthConfig.Endpoint.TokenURL,
url.Values{
"grant_type": {"refresh_token"},
"refresh_token": {tkn.token.RefreshToken},
"client_id": {a.oAuthConfig.ClientID},
"client_secret": {a.oAuthConfig.ClientSecret},
},
)
if err != nil {
return nil, errors.Wrap(err, "refreshing token")
}
defer resp.Body.Close()
var t oauth2.Token
if err := json.NewDecoder(resp.Body).Decode(&t); err != nil {
return nil, errors.Wrap(err, "decoding refreshed token")
}
// update the cache
delete(a.tokenCache, bearer)
delete(a.groupsCache, bearer)
bearer = t.AccessToken
a.tokenCache[bearer] = cachedToken{time.Now(), &t}
}
// 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(bearer, &jwt.MapClaims{})
// well-formed-ness check
if token == nil || token.Claims == nil || err != nil {
return nil, fmt.Errorf("parsing bearer token: %v", err)
}
claims := *token.Claims.(*jwt.MapClaims)
// expiry check
if exp, ok := claims["exp"].(string); ok {
if expiry, err := strconv.ParseInt(exp, 10, 64); err != nil || expiry < time.Now().UTC().Unix() {
return nil, fmt.Errorf("token is expired")
}
}
userInfo := UserInfo{
UserID: claims["oid"].(string),
UserName: claims["name"].(string),
Token: bearer,
Groups: []Group{},
}
if userInfo.Groups, err = a.getGroups(bearer); err != nil {
return nil, errors.Wrap(err, "getting groups")
}
return &userInfo, nil
}
// cleanCache removes old items from our cache
func (a *Auth) cleanCache() {
for bearer, tkn := range a.tokenCache {
// if it's been more than 24 hours since the token was cached
if time.Now().Sub(tkn.cacheTime) >= 24*time.Hour {
// remove it from our cache
delete(a.tokenCache, bearer)
}
}
for bearer, tkn := range a.groupsCache {
// if it's been more than 24 hours since the groups were cached
if time.Now().Sub(tkn.cacheTime) >= 24*time.Hour {
// remove it from our cache
delete(a.groupsCache, bearer)
}
}
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 bearer token from a.tokenCache and a.groupsCache
if bearer, err := r.Cookie(a.cookieName); err == nil {
delete(a.tokenCache, bearer.Value)
delete(a.groupsCache, bearer.Value)
}
// clear cookie
http.SetCookie(w, &http.Cookie{
Name: a.cookieName,
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.tokenCache[token.AccessToken] = cachedToken{time.Now(), token}
a.SetCookie(w, token.AccessToken, 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
g, ok := a.groupsCache[token]
if ok && (time.Now().Sub(g.cacheTime) < a.cacheTTL) {
return g.groups, nil
}
req, err := http.NewRequest("GET", a.groupEndpoint, nil)
if err != nil {
return groups.Groups, 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 groups.Groups, errors.Wrap(err, "getting group membership info")
}
defer response.Body.Close()
if err = json.NewDecoder(response.Body).Decode(&groups); err != nil {
return groups.Groups, errors.Wrap(err, "failed unmarshalling group membership response")
}
a.groupsCache[token] = cachedGroups{
cacheTime: time.Now(),
groups: groups.Groups,
}
return groups.Groups, nil
}
func (a *Auth) SetCookie(w http.ResponseWriter, token string, expiry time.Time) error {
http.SetCookie(w, &http.Cookie{
Name: a.cookieName,
Value: token,
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: expiry,
})
return nil
}
func (a *Auth) SetGRPCMetadata(ctx context.Context, md metadata.MD, token string) error {
cookies := []string{}
if c, ok := md["cookie"]; ok {
for _, cookie := range c {
if strings.HasPrefix(cookie, a.cookieName) {
cookie = a.cookieName + "=" + token
}
cookies = append(cookies, cookie)
}
}
md["cookie"] = cookies
return 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
}

View file

@ -0,0 +1,592 @@
package authn
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"os"
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/golang-jwt/jwt"
"github.com/molecula/featurebase/v3/logger"
"golang.org/x/oauth2"
"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"
)
a, err := NewAuth(
logger.NewStandardLogger(os.Stdout),
"http://localhost:10101/",
Scopes,
AuthorizeURL,
TokenURL,
GroupEndpointURL,
LogoutURL,
ClientID,
ClientSecret,
Key,
)
if err != nil {
t.Fatalf("building auth object%s", err)
}
return a
}
func TestAuth(t *testing.T) {
a := NewTestAuth(t)
t.Run("SetCookie", func(t *testing.T) {
w := httptest.NewRecorder()
err := a.SetCookie(w, "a cookie value", 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("SetGRPCMetadata", func(t *testing.T) {
md := metadata.MD{
"cookie": []string{a.cookieName + "=something"},
}
ctx := grpc.NewContextWithServerTransportStream(
metadata.NewIncomingContext(context.TODO(),
md,
),
NewServerTransportStream(),
)
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
t.Fatalf("expected ok, got: %v", ok)
}
err := a.SetGRPCMetadata(ctx, md, "this is a token!")
if 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 cookie string
for _, cookie = range c {
if strings.HasPrefix(cookie, a.cookieName) {
break
}
}
if exp, got := a.cookieName+"=this is a token!", cookie; got != exp {
t.Fatalf("expected '%v', got '%v'", exp, got)
}
})
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",
)
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
errOnRefresh bool
malformed 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 bearer token: token contains an invalid number of segments"),
},
{
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"),
},
{
name: "ExpiredTokenYesRefresh",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
refresh: true,
exp: -17764800,
},
{
name: "ExpiredTokenYesRefreshButError",
uid: "42",
uname: "A. Token",
groups: []Group{
{
GroupID: "ac97c9e2-346b-42a2-b6da-18bcb61a32fe",
GroupName: "adminGroup",
},
},
refresh: true,
errOnRefresh: true,
exp: -17764800,
err: fmt.Errorf("decoding refreshed token: invalid character 'b' looking for beginning of value"),
},
}
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 {
tkn := jwt.New(jwt.SigningMethodHS256)
claims := tkn.Claims.(jwt.MapClaims)
claims["oid"] = test.uid
claims["name"] = test.uname
if test.exp != 0 {
claims["exp"] = strconv.Itoa(int(test.exp))
}
token, err = tkn.SignedString(a.SecretKey())
if err != nil {
t.Fatalf("unexpected error when signing token %v", err)
}
} else {
token = "asdfasdfasdfasdF"
}
if len(test.groups) > 0 {
a.groupsCache[token] = cachedGroups{time.Now(), test.groups}
}
if test.refresh {
var srv *httptest.Server
if !test.errOnRefresh {
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tkn := jwt.New(jwt.SigningMethodHS256)
claims := tkn.Claims.(jwt.MapClaims)
claims["oid"] = test.uid
claims["name"] = test.uname
expiry := strconv.Itoa(int(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": `+expiry+` }`)
}))
} else {
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "bad", http.StatusInternalServerError)
}))
}
defer srv.Close()
a.oAuthConfig.Endpoint.TokenURL = srv.URL
a.tokenCache[token] = cachedToken{
time.Now(),
&oauth2.Token{
AccessToken: token,
RefreshToken: "blah",
Expiry: time.Unix(test.exp, 0),
},
}
}
// do the actual testing
uinfo, err := a.Authenticate(context.TODO(), token)
// 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.tokenCache["oldy"] = cachedToken{now.Add(-24 * time.Hour), &oauth2.Token{}}
a.tokenCache["goldy"] = cachedToken{now.Add(-4 * time.Hour), &oauth2.Token{}}
a.lastCacheClean = now.Add(-45 * time.Minute)
_, _ = a.Authenticate(context.TODO(), "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")
}
if _, ok := a.tokenCache["oldy"]; ok {
t.Errorf("oldy should have been deleted")
}
if _, ok := a.tokenCache["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.tokenCache["oldy"] = cachedToken{now.Add(-24 * time.Hour), &oauth2.Token{}}
a.tokenCache["goldy"] = cachedToken{now.Add(-4 * time.Hour), &oauth2.Token{}}
a.lastCacheClean = now
_, _ = a.Authenticate(context.TODO(), "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")
}
if _, ok := a.tokenCache["oldy"]; !ok {
t.Errorf("oldy should not have been deleted")
}
if _, ok := a.tokenCache["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: "i feel it in the water",
GroupName: "i feel it in the earth",
},
},
},
}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := json.Marshal(
Groups{
Groups: []Group{
{
GroupID: "much that once was is lost",
GroupName: "for none now live who remember it",
},
},
},
)
if err != nil {
t.Fatalf("unexpected error marshalling groups response: %v", err)
}
fmt.Fprintf(w, "%s", body)
}))
a.groupEndpoint = srv.URL
for name, test := range map[string]struct {
token string
groups []Group
}{
"InCache": {
token: "the world is changed",
groups: []Group{
{
GroupID: "i feel it in the water",
GroupName: "i feel it in the earth",
},
},
},
"NotInCache": {
token: "i smell it in the air",
groups: []Group{
{
GroupID: "much that once was is lost",
GroupName: "for none now live who remember it",
},
},
},
} {
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.cookieName,
Value: "test",
Path: "/",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expires: time.Unix(3000000, 0),
},
)
a.groupsCache["test"] = cachedGroups{}
a.tokenCache["test"] = cachedToken{time.Now(), &oauth2.Token{}}
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.cookieName {
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)
}
break
}
}
if _, ok := a.groupsCache["test"]; ok {
t.Fatalf("groups not deleted!")
}
if _, ok := a.tokenCache["test"]; ok {
t.Fatalf("token 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 := strconv.Itoa(int(exp.Unix()))
claims["exp"] = expiry
fresh, err := tkn.SignedString(a.SecretKey())
if err != nil {
t.Fatalf("unexpected error when signing token %v", err)
}
freshToken := oauth2.Token{
AccessToken: fresh,
RefreshToken: "blah",
Expiry: exp,
}
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)
}
cachedToken := a.tokenCache[fresh].token
if cachedToken.AccessToken != freshToken.AccessToken {
t.Fatalf("expected %v, got %v", freshToken.AccessToken, cachedToken.AccessToken)
}
if cachedToken.RefreshToken != freshToken.RefreshToken {
t.Fatalf("expected %v, got %v", freshToken.RefreshToken, cachedToken.RefreshToken)
}
if cachedToken.Expiry.Sub(freshToken.Expiry) > time.Second {
t.Fatalf("expected %v, got %v", freshToken.Expiry, cachedToken.Expiry)
}
})
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
}

142
authz/authorization.go Normal file
View file

@ -0,0 +1,142 @@
// 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 authz
import (
"fmt"
"io"
"io/ioutil"
"github.com/molecula/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 := ioutil.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
}

316
authz/authorization_test.go Normal file
View file

@ -0,0 +1,316 @@
// 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 authz_test
import (
"fmt"
"reflect"
"sort"
"strings"
"testing"
"github.com/molecula/featurebase/v3/authn"
"github.com/molecula/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)
}
})
}
}

View file

@ -1,423 +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 boltdb
import (
"bytes"
"encoding/binary"
"fmt"
"sort"
"sync"
"time"
"github.com/cespare/xxhash"
"github.com/boltdb/bolt"
"github.com/pilosa/pilosa/v2"
"github.com/pkg/errors"
)
// attrBlockSize is the size of attribute blocks for anti-entropy.
const attrBlockSize = 100
// 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) pilosa.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 errors.Wrap(err, "opening storage")
}
s.db = db
// Initialize database.
if err := s.db.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucketIfNotExists([]byte("attrs"))
return err
}); err != nil {
return errors.Wrap(err, "initializing")
}
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)
return err
}); err != nil {
return nil, errors.Wrap(err, "finding attributes")
}
// Add to cache.
s.attrCache.Set(id, m)
return m, nil
}
// 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 errors.Wrap(err, "checking attrs")
} 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 errors.Wrap(err, "updating store")
}
// 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.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
// 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() (blocks []pilosa.AttrBlock, err error) {
err = s.db.View(func(tx *bolt.Tx) error {
// Wrap cursor to segment by block.
cur := newBlockCursor(tx.Bucket([]byte("attrs")).Cursor(), attrBlockSize)
// Iterate over each block.
for cur.nextBlock() {
block := pilosa.AttrBlock{ID: cur.blockID()}
// Compute checksum of every key/value in block.
h := xxhash.New()
for k, v := cur.next(); k != nil; k, v = cur.next() {
// hash function writes don't usually need to be checked
_, _ = h.Write(k)
_, _ = h.Write(v)
}
block.Checksum = h.Sum(nil)
// Append block.
blocks = append(blocks, block)
}
return nil
})
if err != nil {
return nil, errors.Wrap(err, "getting blocks")
}
return blocks, nil
}
// BlockData returns all data for a single block.
func (s *attrStore) BlockData(i uint64) (m map[uint64]map[string]interface{}, err error) {
m = make(map[uint64]map[string]interface{})
// Start read-only transaction.
err = s.db.View(func(tx *bolt.Tx) error {
// Move to the start of the block.
min := u64tob(i * attrBlockSize)
max := u64tob((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.
attrs, err := pilosa.DecodeAttrs(v)
if err != nil {
return errors.Wrap(err, "decoding attrs")
}
m[btou64(k)] = attrs
}
return nil
})
if err != nil {
return nil, errors.Wrap(err, "getting block data")
}
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
}
return pilosa.DecodeAttrs(v)
}
// 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 := pilosa.EncodeAttrs(attr)
if err != nil {
return nil, errors.Wrap(err, "encoding attrs")
}
if err := tx.Bucket([]byte("attrs")).Put(u64tob(id), buf); err != nil {
return nil, errors.Wrap(err, "saving attrs")
}
return attr, nil
}
// 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{})
// 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
}
// 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 { // nolint: unparam
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
}

View file

@ -1,39 +1,49 @@
// 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 2021 Molecula Corp. All rights reserved.
package boltdb
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"io"
"os"
"path/filepath"
"sync"
"time"
"github.com/boltdb/bolt"
"github.com/pilosa/pilosa/v2"
"github.com/molecula/featurebase/v3"
"github.com/pkg/errors"
bolt "go.etcd.io/bbolt"
"runtime/pprof"
)
var _ = pprof.StartCPUProfile
var (
// ErrTranslateStoreClosed is returned when reading from an TranslateEntryReader
// and the underlying store is closed.
ErrTranslateStoreClosed = errors.New("boltdb: translate store closing")
// ErrTranslateKeyNotFound is returned when translating key
// and the underlying store returns an empty set
ErrTranslateKeyNotFound = errors.New("boltdb: translating key returned empty set")
bucketKeys = []byte("keys")
bucketIDs = []byte("ids")
)
const (
// snapshotExt is the file extension used for an in-process snapshot.
snapshotExt = ".snapshotting"
errFmtTranslateBucketNotFound = "boltdb: translate bucket '%s' not found"
)
// OpenTranslateStore opens and initializes a boltdb translation store.
func OpenTranslateStore(path, index, field string) (pilosa.TranslateStore, error) {
s := NewTranslateStore(index, field)
func OpenTranslateStore(path, index, field string, partitionID, partitionN int, fsyncEnabled bool) (pilosa.TranslateStore, error) {
s := NewTranslateStore(index, field, partitionID, partitionN, fsyncEnabled)
s.Path = path
if err := s.Open(); err != nil {
return nil, err
@ -45,46 +55,69 @@ func OpenTranslateStore(path, index, field string) (pilosa.TranslateStore, error
var _ pilosa.TranslateStore = &TranslateStore{}
// TranslateStore is an on-disk storage engine for translating string-to-uint64 values.
// An empty string will be converted into the sentinel byte slice:
// var emptyKey = []byte{
// 0x00, 0x00, 0x00,
// 0x4d, 0x54, 0x4d, 0x54, // MTMT
// 0x00,
// 0xc2, 0xa0, // NO-BREAK SPACE
// 0x00,
// }
type TranslateStore struct {
mu sync.RWMutex
db *bolt.DB
index string
field string
index string
field string
partitionID int
partitionN int
once sync.Once
closing chan struct{}
readOnly bool
writeNotify chan struct{}
readOnly bool
fsyncEnabled bool
writeNotify chan struct{}
// File path to database file.
Path string
}
// NewTranslateStore returns a new instance of TranslateStore.
func NewTranslateStore(index, field string) *TranslateStore {
func NewTranslateStore(index, field string, partitionID, partitionN int, fsyncEnabled bool) *TranslateStore {
return &TranslateStore{
index: index,
field: field,
closing: make(chan struct{}),
writeNotify: make(chan struct{}),
index: index,
field: field,
partitionID: partitionID,
partitionN: partitionN,
closing: make(chan struct{}),
writeNotify: make(chan struct{}),
fsyncEnabled: fsyncEnabled,
}
}
// Open opens the translate file.
func (s *TranslateStore) Open() (err error) {
// add the path to the problem database if we panic handling it.
defer func() {
r := recover()
if r != nil {
panic(fmt.Sprintf("pilosa/boltdb/TranslateStore.Open(s.Path='%v') panic with '%v'", s.Path, r))
}
}()
if err := os.MkdirAll(filepath.Dir(s.Path), 0777); err != nil {
return errors.Wrapf(err, "mkdir %s", filepath.Dir(s.Path))
} else if s.db, err = bolt.Open(s.Path, 0666, &bolt.Options{Timeout: 1 * time.Second}); err != nil {
} else if s.db, err = bolt.Open(s.Path, 0666, &bolt.Options{Timeout: 1 * time.Second, NoSync: !s.fsyncEnabled}); err != nil {
return errors.Wrapf(err, "open file: %s", err)
}
// Initialize buckets.
if err := s.db.Update(func(tx *bolt.Tx) error {
if _, err := tx.CreateBucketIfNotExists([]byte("keys")); err != nil {
if _, err := tx.CreateBucketIfNotExists(bucketKeys); err != nil {
return err
} else if _, err := tx.CreateBucketIfNotExists([]byte("ids")); err != nil {
} else if _, err := tx.CreateBucketIfNotExists(bucketIDs); err != nil {
return err
}
return nil
@ -108,6 +141,11 @@ func (s *TranslateStore) Close() (err error) {
return nil
}
// PartitionID returns the partition id the store was initialized with.
func (s *TranslateStore) PartitionID() int {
return s.partitionID
}
// ReadOnly returns true if the store is in read-only mode.
func (s *TranslateStore) ReadOnly() bool {
s.mu.RLock()
@ -135,109 +173,127 @@ func (s *TranslateStore) Size() int64 {
return tx.Size()
}
// TranslateKeys converts a string key to an integer ID.
// If key does not have an associated id then one is created.
func (s *TranslateStore) TranslateKey(key string) (id uint64, _ error) {
// Find id by key under read lock.
if err := s.db.View(func(tx *bolt.Tx) error {
id = findIDByKey(tx.Bucket([]byte("keys")), key)
return nil
}); err != nil {
return 0, err
} else if id != 0 {
return id, nil
}
if s.ReadOnly() {
return 0, pilosa.ErrTranslateStoreReadOnly
}
// Find or create id under write lock.
var written bool
if err := s.db.Update(func(tx *bolt.Tx) (err error) {
bkt := tx.Bucket([]byte("keys"))
if id = findIDByKey(bkt, key); id != 0 {
return nil
} else if id, err = bkt.NextSequence(); err != nil {
return err
} else if err := bkt.Put([]byte(key), u64tob(id)); err != nil {
return err
} else if err := tx.Bucket([]byte("ids")).Put(u64tob(id), []byte(key)); err != nil {
return err
// FindKeys looks up the ID for each key.
// Keys are not created if they do not exist.
// Missing keys are not considered errors, so the length of the result may be less than that of the input.
func (s *TranslateStore) FindKeys(keys ...string) (map[string]uint64, error) {
result := make(map[string]uint64, len(keys))
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(bucketKeys)
if bkt == nil {
return errors.Errorf(errFmtTranslateBucketNotFound, bucketKeys)
}
for _, key := range keys {
id, _ := findIDByKey(bkt, key)
if id == 0 {
// The key does not exist.
continue
}
result[key] = id
}
written = true
return nil
}); err != nil {
return 0, err
})
if err != nil {
return nil, err
}
if written {
s.notifyWrite()
}
return id, nil
return result, nil
}
// TranslateKeys converts a string key to an integer ID.
// If key does not have an associated id then one is created.
func (s *TranslateStore) TranslateKeys(keys []string) (ids []uint64, _ error) {
if len(keys) == 0 {
return nil, nil
}
// Allocate slice for ID mapping.
ids = make([]uint64, len(keys))
// Find ids by key under read lock.
var found int
if err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte("keys"))
for i, key := range keys {
if id := findIDByKey(bkt, key); id != 0 {
ids[i] = id
found++
}
}
return nil
}); err != nil {
return nil, err
} else if found == len(keys) {
return ids, nil
}
// translateTransactionSize governs the number of writes to a single
// boltDB bucket we will make in a single db.Update(), before starting
// a new Update. We do this because Put() is quadratic, but Commit is
// expensive enough that we want to do a fair number of updates before
// paying for it.
const translateTransactionSize = 16384
// CreateKeys maps all keys to IDs, creating the IDs if they do not exist.
// If the translator is read-only, this will return an error.
func (s *TranslateStore) CreateKeys(keys ...string) (map[string]uint64, error) {
if s.ReadOnly() {
return ids, pilosa.ErrTranslateStoreReadOnly
return nil, pilosa.ErrTranslateStoreReadOnly
}
// Find or create ids under write lock if any keys were not found.
var written bool
if err := s.db.Update(func(tx *bolt.Tx) (err error) {
bkt := tx.Bucket([]byte("keys"))
for i, key := range keys {
if ids[i] != 0 {
continue
written := false
result := make(map[string]uint64, len(keys))
idScratch := make([]byte, translateTransactionSize*8)
for len(keys) > 0 {
// boltdb performs badly if you write really large numbers of
// keys all at once...
err := s.db.Update(func(tx *bolt.Tx) error {
keyBucket := tx.Bucket(bucketKeys)
if keyBucket == nil {
return errors.Errorf(errFmtTranslateBucketNotFound, bucketKeys)
}
if ids[i] = findIDByKey(bkt, key); ids[i] != 0 {
continue
} else if ids[i], err = bkt.NextSequence(); err != nil {
return err
} else if err := bkt.Put([]byte(key), u64tob(ids[i])); err != nil {
return err
} else if err := tx.Bucket([]byte("ids")).Put(u64tob(ids[i]), []byte(key)); err != nil {
return err
idBucket := tx.Bucket(bucketIDs)
if idBucket == nil {
return errors.Errorf(errFmtTranslateBucketNotFound, bucketIDs)
}
written = true
puts := 0
for idx, key := range keys {
id, boltKey := findIDByKey(keyBucket, key)
if id != 0 {
result[key] = id
continue
}
id = pilosa.GenerateNextPartitionedID(s.index, maxID(tx), s.partitionID, s.partitionN)
idBytes := idScratch[puts*8 : puts*8+8]
binary.BigEndian.PutUint64(idBytes, id)
puts++
if err := keyBucket.Put(boltKey, idBytes); err != nil {
return err
} else if err := idBucket.Put(idBytes, boltKey); err != nil {
return err
}
result[key] = id
written = true
if puts == translateTransactionSize {
keys = keys[idx+1:]
return nil
}
}
keys = keys[len(keys):]
return nil
})
if err != nil {
return nil, err
}
return nil
}); err != nil {
return nil, err
}
if written {
s.notifyWrite()
}
return ids, nil
return result, nil
}
// Match finds the IDs of all keys matching a filter.
func (s *TranslateStore) Match(filter func([]byte) bool) ([]uint64, error) {
var matches []uint64
err := s.db.View(func(tx *bolt.Tx) error {
// This uses the id bucket instead of the key bucket so that matches are produced in sorted order.
idBucket := tx.Bucket(bucketIDs)
if idBucket == nil {
return errors.Errorf(errFmtTranslateBucketNotFound, bucketIDs)
}
return idBucket.ForEach(func(id, key []byte) error {
if bytes.Equal(key, emptyKey) {
key = nil
}
if filter(key) {
matches = append(matches, btou64(id))
}
return nil
})
})
if err != nil {
return nil, err
}
return matches, nil
}
// TranslateID converts an integer ID to a string key.
@ -248,7 +304,7 @@ func (s *TranslateStore) TranslateID(id uint64) (string, error) {
return "", err
}
defer func() { _ = tx.Rollback() }()
return findKeyByID(tx.Bucket([]byte("ids")), id), nil
return findKeyByID(tx.Bucket(bucketIDs), id), nil
}
// TranslateIDs converts a list of integer IDs to a list of string keys.
@ -263,9 +319,11 @@ func (s *TranslateStore) TranslateIDs(ids []uint64) ([]string, error) {
}
defer func() { _ = tx.Rollback() }()
bucket := tx.Bucket(bucketIDs)
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = findKeyByID(tx.Bucket([]byte("ids")), id)
keys[i] = findKeyByID(bucket, id)
}
return keys, nil
}
@ -273,9 +331,9 @@ func (s *TranslateStore) TranslateIDs(ids []uint64) ([]string, error) {
// ForceSet writes the id/key pair to the store even if read only. Used by replication.
func (s *TranslateStore) ForceSet(id uint64, key string) error {
if err := s.db.Update(func(tx *bolt.Tx) (err error) {
if err := tx.Bucket([]byte("keys")).Put([]byte(key), u64tob(id)); err != nil {
if err := tx.Bucket(bucketKeys).Put([]byte(key), u64tob(id)); err != nil {
return err
} else if err := tx.Bucket([]byte("ids")).Put(u64tob(id), []byte(key)); err != nil {
} else if err := tx.Bucket(bucketIDs).Put(u64tob(id), []byte(key)); err != nil {
return err
}
return nil
@ -286,7 +344,7 @@ func (s *TranslateStore) ForceSet(id uint64, key string) error {
return nil
}
// Reader returns a reader that streams the underlying data file.
// EntryReader returns a reader that streams the underlying data file.
func (s *TranslateStore) EntryReader(ctx context.Context, offset uint64) (pilosa.TranslateEntryReader, error) {
ctx, cancel := context.WithCancel(ctx)
return &TranslateEntryReader{ctx: ctx, cancel: cancel, store: s, offset: offset}, nil
@ -311,9 +369,7 @@ func (s *TranslateStore) notifyWrite() {
// MaxID returns the highest id in the store.
func (s *TranslateStore) MaxID() (max uint64, err error) {
if err := s.db.View(func(tx *bolt.Tx) error {
if key, _ := tx.Bucket([]byte("ids")).Cursor().Last(); key != nil {
max = btou64(key)
}
max = maxID(tx)
return nil
}); err != nil {
return 0, err
@ -321,6 +377,61 @@ func (s *TranslateStore) MaxID() (max uint64, err error) {
return max, nil
}
// WriteTo writes the contents of the store to the writer.
func (s *TranslateStore) WriteTo(w io.Writer) (int64, error) {
tx, err := s.db.Begin(false)
if err != nil {
return 0, err
}
defer func() { _ = tx.Rollback() }()
return tx.WriteTo(w)
}
// ReadFrom reads the content and overwrites the existing store.
func (s *TranslateStore) ReadFrom(r io.Reader) (n int64, err error) {
// Close store.
if err := s.Close(); err != nil {
return 0, errors.Wrap(err, "closing store")
}
// Create a temporary file to snapshot to.
snapshotPath := s.Path + snapshotExt
file, err := os.Create(snapshotPath)
if err != nil {
return n, errors.Wrap(err, "creating snapshot file")
}
// Write payload to snapshot.
if n, err = io.Copy(file, r); err != nil {
file.Close()
return n, errors.Wrap(err, "snapshot write to")
}
// we close the file here so we don't still have it open when trying
// to open it in a moment.
file.Close()
// Move snapshot to data file location.
if err := os.Rename(snapshotPath, s.Path); err != nil {
return n, errors.Wrap(err, "renaming snapshot")
}
// Re-open the store.
if err := s.Open(); err != nil {
return n, errors.Wrap(err, "re-opening store")
}
return n, nil
}
// MaxID returns the highest id in the store.
func maxID(tx *bolt.Tx) uint64 {
if key, _ := tx.Bucket(bucketIDs).Cursor().Last(); key != nil {
return btou64(key)
}
return 0
}
type TranslateEntryReader struct {
ctx context.Context
store *TranslateStore
@ -353,7 +464,7 @@ func (r *TranslateEntryReader) ReadEntry(entry *pilosa.TranslateEntry) error {
var found bool
if err := r.store.db.View(func(tx *bolt.Tx) error {
// Find ID/key lookup at offset or later.
cur := tx.Bucket([]byte("ids")).Cursor()
cur := tx.Bucket(bucketIDs).Cursor()
key, value := cur.Seek(u64tob(r.offset))
if key == nil {
return nil
@ -387,13 +498,43 @@ func (r *TranslateEntryReader) ReadEntry(entry *pilosa.TranslateEntry) error {
}
}
func findIDByKey(bkt *bolt.Bucket, key string) uint64 {
if value := bkt.Get([]byte(key)); value != nil {
return btou64(value)
// emptyKey is a sentinel byte slice which stands for "" as a key.
var emptyKey = []byte{
0x00, 0x00, 0x00,
0x4d, 0x54, 0x4d, 0x54, // MTMT
0x00,
0xc2, 0xa0, // NO-BREAK SPACE
0x00,
}
func findIDByKey(bkt *bolt.Bucket, key string) (uint64, []byte) {
var boltKey []byte
if key == "" {
boltKey = emptyKey
} else {
boltKey = []byte(key)
}
return 0
if value := bkt.Get(boltKey); value != nil {
return btou64(value), boltKey
}
return 0, boltKey
}
func findKeyByID(bkt *bolt.Bucket, id uint64) string {
return string(bkt.Get(u64tob(id)))
boltKey := bkt.Get(u64tob(id))
if bytes.Equal(boltKey, emptyKey) {
return ""
}
return string(boltKey)
}
// 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) }

View file

@ -1,125 +1,97 @@
// 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 2021 Molecula Corp. All rights reserved.
package boltdb_test
import (
"bytes"
"context"
"io/ioutil"
"os"
"fmt"
"reflect"
"strconv"
"testing"
"time"
"github.com/pilosa/pilosa/v2"
"github.com/pilosa/pilosa/v2/boltdb"
"github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/boltdb"
"github.com/molecula/featurebase/v3/testhook"
"github.com/molecula/featurebase/v3/topology"
)
func TestTranslateStore_TranslateKey(t *testing.T) {
s := MustOpenNewTranslateStore()
//var vv = pilosa.VV
func TestTranslateStore_CreateKeys(t *testing.T) {
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Ensure initial key translates to ID 1.
if id, err := s.TranslateKey("foo"); err != nil {
ids, err := s.CreateKeys("abc", "abc")
if err != nil {
t.Fatal(err)
} else if got, want := id, uint64(1); got != want {
t.Fatalf("TranslateKey()=%d, want %d", got, want)
} else if _, ok := ids["abc"]; !ok {
t.Fatalf(`missing "abc"; got %v`, ids)
} else if len(ids) > 1 {
t.Fatalf("expected one key, got %d in %v", len(ids), ids)
}
// Ensure next key autoincrements.
if id, err := s.TranslateKey("bar"); err != nil {
// Ensure different keys translate to different IDs.
ids1, err := s.CreateKeys("foo", "bar")
if err != nil {
t.Fatal(err)
} else if got, want := id, uint64(2); got != want {
t.Fatalf("TranslateKey()=%d, want %d", got, want)
}
// Ensure retranslating existing key returns original ID.
if id, err := s.TranslateKey("foo"); err != nil {
t.Fatal(err)
} else if got, want := id, uint64(1); got != want {
t.Fatalf("TranslateKey()=%d, want %d", got, want)
}
}
func TestTranslateStore_TranslateKeys(t *testing.T) {
s := MustOpenNewTranslateStore()
defer MustCloseTranslateStore(s)
// Ensure initial keys translate to incrementing IDs.
if ids, err := s.TranslateKeys([]string{"foo", "bar"}); err != nil {
t.Fatal(err)
} else if got, want := ids[0], uint64(1); got != want {
t.Fatalf("TranslateKeys()[0]=%d, want %d", got, want)
} else if got, want := ids[1], uint64(2); got != want {
t.Fatalf("TranslateKeys()[1]=%d, want %d", got, want)
} else if foo, bar := ids1["foo"], ids1["bar"]; foo == bar {
t.Fatalf(`"foo" and "bar" map back to the same ID %d`, foo)
}
// Ensure retranslation returns original IDs.
if ids, err := s.TranslateKeys([]string{"foo", "bar"}); err != nil {
if ids, err := s.CreateKeys("bar", "foo"); err != nil {
t.Fatal(err)
} else if got, want := ids[0], uint64(1); got != want {
t.Fatalf("TranslateKeys()[0]=%d, want %d", got, want)
} else if got, want := ids[1], uint64(2); got != want {
t.Fatalf("TranslateKeys()[1]=%d, want %d", got, want)
} else if !reflect.DeepEqual(ids, ids1) {
t.Fatalf("retranslation produced result %v which is different from original translation %v", ids, ids1)
}
// Ensure retranslating with existing and non-existing keys returns correctly.
if ids, err := s.TranslateKeys([]string{"foo", "baz", "bar"}); err != nil {
if ids, err := s.CreateKeys("foo", "baz", "bar"); err != nil {
t.Fatal(err)
} else if got, want := ids[0], uint64(1); got != want {
t.Fatalf("TranslateKeys()[0]=%d, want %d", got, want)
} else if got, want := ids[1], uint64(3); got != want {
t.Fatalf("TranslateKeys()[1]=%d, want %d", got, want)
} else if got, want := ids[2], uint64(2); got != want {
t.Fatalf("TranslateKeys()[2]=%d, want %d", got, want)
} else if got, want := ids["foo"], ids1["foo"]; got != want {
t.Fatalf(`mismatched ID %d for "foo" (previously %d)`, got, want)
} else if _, ok := ids["baz"]; !ok {
t.Fatalf(`missing translation for "baz"; got %v`, ids)
} else if got, want := ids["bar"], ids1["bar"]; got != want {
t.Fatalf(`mismatched ID %d for "bar" (previously %d)`, got, want)
}
}
func TestTranslateStore_TranslateID(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Setup initial keys.
if _, err := s.TranslateKey("foo"); err != nil {
t.Fatal(err)
} else if _, err := s.TranslateKey("bar"); err != nil {
ids, err := s.CreateKeys("foo", "bar", "")
if err != nil {
t.Fatal(err)
}
// Ensure IDs can be translated back to keys.
if key, err := s.TranslateID(1); err != nil {
t.Fatal(err)
} else if got, want := key, "foo"; got != want {
t.Fatalf("TranslateID()=%s, want %s", got, want)
}
if key, err := s.TranslateID(2); err != nil {
t.Fatal(err)
} else if got, want := key, "bar"; got != want {
t.Fatalf("TranslateID()=%s, want %s", got, want)
for key, id := range ids {
k, err := s.TranslateID(id)
if err != nil {
t.Fatal(err)
}
if k != key {
t.Fatalf("TranslateID()=%s, want %s", k, key)
}
}
}
func TestTranslateStore_TranslateIDs(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Setup initial keys.
if _, err := s.TranslateKeys([]string{"foo", "bar"}); err != nil {
ids, err := s.CreateKeys("foo", "bar")
if err != nil {
t.Fatal(err)
}
// Ensure IDs can be translated back to keys.
if keys, err := s.TranslateIDs([]uint64{1, 2, 3}); err != nil {
if keys, err := s.TranslateIDs([]uint64{ids["foo"], ids["bar"], 1}); err != nil {
t.Fatal(err)
} else if got, want := keys[0], "foo"; got != want {
t.Fatalf("TranslateIDs()[0]=%s, want %s", got, want)
@ -130,13 +102,114 @@ func TestTranslateStore_TranslateIDs(t *testing.T) {
}
}
func TestTranslateStore_FindKeys(t *testing.T) {
cases := []struct {
name string
data []string
lookup []string
}{
{
name: "All",
data: []string{"plugh", "xyzzy", "h"},
lookup: []string{"plugh", "xyzzy", "h"},
},
{
name: "Extra",
data: []string{"plugh", "xyzzy", "h"},
lookup: []string{"plugh", "xyzzy", "h", "65"},
},
{
name: "None",
data: []string{"a", "b", "c"},
lookup: []string{"d", "e"},
},
{
name: "Empty",
lookup: []string{"h"},
},
{
name: "LookupNothing",
},
}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
var naiveMap map[string]uint64
if c.data != nil {
// Load in key data.
keys := c.data
ids, err := s.CreateKeys(keys...)
if err != nil {
t.Errorf("failed to import keys: %v", err)
return
}
if len(ids) != len(keys) {
t.Errorf("mapped %d keys to %d ids", len(keys), len(ids))
return
}
naiveMap = ids
}
// Compute expected lookup result.
result := map[string]uint64{}
for _, key := range c.lookup {
id, ok := naiveMap[key]
if !ok {
// The key is expected to be missing.
continue
}
result[key] = id
}
// Find the keys.
found, err := s.FindKeys(c.lookup...)
if err != nil {
t.Errorf("failed to find keys: %v", err)
} else if !reflect.DeepEqual(result, found) {
t.Errorf("expected %v but found %v", result, found)
}
})
}
}
func TestTranslateStore_MaxID(t *testing.T) {
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Generate a bunch of keys.
var lastk uint64
for i := 0; i < 1026; i++ {
key := strconv.Itoa(i)
ids, err := s.CreateKeys(key)
if err != nil {
t.Fatalf("translating %d: %v", i, err)
}
lastk = ids[key]
}
// Verify the max ID.
max, err := s.MaxID()
if err != nil {
t.Fatalf("checking max ID: %v", err)
}
if max != lastk {
t.Fatalf("last key is %d but max is %d", lastk, max)
}
}
func TestTranslateStore_EntryReader(t *testing.T) {
t.Run("OK", func(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Create multiple new keys.
if _, err := s.TranslateKeys([]string{"foo", "bar"}); err != nil {
ids1, err := s.CreateKeys("foo", "bar")
if err != nil {
t.Fatal(err)
}
@ -151,7 +224,7 @@ func TestTranslateStore_EntryReader(t *testing.T) {
// Read first entry.
if err := r.ReadEntry(&entry); err != nil {
t.Fatal(err)
} else if got, want := entry.ID, uint64(1); got != want {
} else if got, want := entry.ID, ids1["foo"]; got != want {
t.Fatalf("ReadEntry() ID=%d, want %d", got, want)
} else if got, want := entry.Key, "foo"; got != want {
t.Fatalf("ReadEntry() Key=%s, want %s", got, want)
@ -160,21 +233,22 @@ func TestTranslateStore_EntryReader(t *testing.T) {
// Read next entry.
if err := r.ReadEntry(&entry); err != nil {
t.Fatal(err)
} else if got, want := entry.ID, uint64(2); got != want {
} else if got, want := entry.ID, ids1["bar"]; got != want {
t.Fatalf("ReadEntry() ID=%d, want %d", got, want)
} else if got, want := entry.Key, "bar"; got != want {
t.Fatalf("ReadEntry() Key=%s, want %s", got, want)
}
// Insert next key while reader is open.
if _, err := s.TranslateKey("baz"); err != nil {
ids2, err := s.CreateKeys("baz")
if err != nil {
t.Fatal(err)
}
// Read newly created entry.
if err := r.ReadEntry(&entry); err != nil {
t.Fatal(err)
} else if got, want := entry.ID, uint64(3); got != want {
} else if got, want := entry.ID, ids2["baz"]; got != want {
t.Fatalf("ReadEntry() ID=%d, want %d", got, want)
} else if got, want := entry.Key, "baz"; got != want {
t.Fatalf("ReadEntry() Key=%s, want %s", got, want)
@ -188,7 +262,7 @@ func TestTranslateStore_EntryReader(t *testing.T) {
// Ensure reader will read as soon as a new write comes in using WriteNotify().
t.Run("WriteNotify", func(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Start reader from initial position.
@ -198,20 +272,25 @@ func TestTranslateStore_EntryReader(t *testing.T) {
}
defer r.Close()
// cache holds the translated key id so we can check it later
cache := make(chan uint64)
// Insert key in separate goroutine.
// Sleep momentarily to reader hangs.
translateErr := make(chan error)
go func() {
time.Sleep(100 * time.Millisecond)
if _, err := s.TranslateKey("foo"); err != nil {
ids, err := s.CreateKeys("foo")
if err != nil {
translateErr <- err
}
cache <- ids["foo"]
}()
var entry pilosa.TranslateEntry
if err := r.ReadEntry(&entry); err != nil {
t.Fatal(err)
} else if got, want := entry.ID, uint64(1); got != want {
} else if got, want := entry.ID, <-cache; got != want {
t.Fatalf("ReadEntry() ID=%d, want %d", got, want)
} else if got, want := entry.Key, "foo"; got != want {
t.Fatalf("ReadEntry() Key=%s, want %s", got, want)
@ -226,7 +305,7 @@ func TestTranslateStore_EntryReader(t *testing.T) {
// Ensure exits read on close.
t.Run("Close", func(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Start reader from initial position.
@ -260,7 +339,7 @@ func TestTranslateStore_EntryReader(t *testing.T) {
// Ensure exits read on store close.
t.Run("StoreClose", func(t *testing.T) {
s := MustOpenNewTranslateStore()
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
// Start reader from initial position.
@ -294,22 +373,90 @@ func TestTranslateStore_EntryReader(t *testing.T) {
}
// MustNewTranslateStore returns a new TranslateStore with a temporary path.
func MustNewTranslateStore() *boltdb.TranslateStore {
f, err := ioutil.TempFile("", "")
func MustNewTranslateStore(tb testing.TB) *boltdb.TranslateStore {
f, err := testhook.TempFile(tb, "translate-store")
if err != nil {
panic(err)
} else if err := f.Close(); err != nil {
panic(err)
}
s := boltdb.NewTranslateStore("I", "F")
s := boltdb.NewTranslateStore("I", "F", 0, topology.DefaultPartitionN, false)
s.Path = f.Name()
return s
}
func TestTranslateStore_ReadWrite(t *testing.T) {
t.Run("WriteTo_ReadFrom", func(t *testing.T) {
s := MustOpenNewTranslateStore(t)
defer MustCloseTranslateStore(s)
batch0 := []string{}
for i := 0; i < 100; i++ {
batch0 = append(batch0, fmt.Sprintf("key%d", i))
}
batch1 := []string{}
for i := 100; i < 200; i++ {
batch1 = append(batch1, fmt.Sprintf("key%d", i))
}
// Populate the store with the keys in batch0.
batch0IDs, err := s.CreateKeys(batch0...)
if err != nil {
t.Fatal(err)
}
// Put the contents of the store into a buffer.
buf := bytes.NewBuffer(nil)
expN := int64(32768)
// After this, the buffer should contain batch0.
if n, err := s.WriteTo(buf); err != nil {
t.Fatalf("writing to buffer: %s", err)
} else if n != expN {
t.Fatalf("expected buffer size: %d, but got: %d", expN, n)
}
// Populate the store with the keys in batch1.
batch1IDs, err := s.CreateKeys(batch1...)
if err != nil {
t.Fatal(err)
}
expIDs := map[string]uint64{
"key50": batch0IDs["key50"],
"key150": batch1IDs["key150"],
}
// Check the IDs for a key from each batch.
if ids, err := s.FindKeys("key50", "key150"); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(expIDs, ids) {
t.Fatalf("first expected ids: %v, but got: %v", expIDs, ids)
}
// Reset the contents of the store with the data in the buffer.
if n, err := s.ReadFrom(buf); err != nil {
t.Fatalf("reading from buffer: %s", err)
} else if n != expN {
t.Fatalf("expected buffer size: %d, but got: %d", expN, n)
}
// This time, we expect the second key to be different because
// we overwrote the store, and then just set that key.
if ids, err := s.CreateKeys("key50", "key150"); err != nil {
t.Fatal(err)
} else if ids["key50"] != expIDs["key50"] {
t.Fatalf("last expected ids[key50]: %d, but got: %d", expIDs["key50"], ids["key50"])
} else if ids["key150"] == expIDs["key150"] {
t.Fatalf("last expected different ids[key150]: %d, but got: %d", expIDs["key150"], ids["key150"])
}
})
}
// MustOpenNewTranslateStore returns a new, opened TranslateStore.
func MustOpenNewTranslateStore() *boltdb.TranslateStore {
s := MustNewTranslateStore()
func MustOpenNewTranslateStore(tb testing.TB) *boltdb.TranslateStore {
s := MustNewTranslateStore(tb)
if err := s.Open(); err != nil {
panic(err)
}
@ -320,7 +467,5 @@ func MustOpenNewTranslateStore() *boltdb.TranslateStore {
func MustCloseTranslateStore(s *boltdb.TranslateStore) {
if err := s.Close(); err != nil {
panic(err)
} else if err := os.Remove(s.Path); err != nil {
panic(err)
}
}

View file

@ -1,22 +1,10 @@
// 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 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"fmt"
"github.com/molecula/featurebase/v3/topology"
"github.com/pkg/errors"
)
@ -26,11 +14,22 @@ type Serializer interface {
Unmarshal([]byte, Message) error
}
// 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(*Node, Message) error
SendTo(*topology.Node, Message) error
}
// Message is the interface implemented by all core pilosa types which can be serialized to messages.
@ -49,7 +48,7 @@ func (nopBroadcaster) SendSync(Message) error { return nil }
func (nopBroadcaster) SendAsync(Message) error { return nil }
// SendTo is a no-op implementation of Broadcaster SendTo method.
func (nopBroadcaster) SendTo(*Node, Message) error { return nil }
func (nopBroadcaster) SendTo(*topology.Node, Message) error { return nil }
// Broadcast message types.
const (
@ -63,12 +62,14 @@ const (
messageTypeClusterStatus
messageTypeResizeInstruction
messageTypeResizeInstructionComplete
messageTypeSetCoordinator
messageTypeUpdateCoordinator
messageTypeNodeState
messageTypeRecalculateCaches
messageTypeLoadSchemaMessage
messageTypeNodeEvent
messageTypeNodeStatus
messageTypeTransaction
messageTypeResizeNodeMessage
messageTypeResizeAbortMessage
)
// MarshalInternalMessage serializes the pilosa message and adds pilosa internal
@ -104,18 +105,22 @@ func getMessage(typ byte) Message {
return &ResizeInstruction{}
case messageTypeResizeInstructionComplete:
return &ResizeInstructionComplete{}
case messageTypeSetCoordinator:
return &SetCoordinatorMessage{}
case messageTypeUpdateCoordinator:
return &UpdateCoordinatorMessage{}
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 messageTypeResizeNodeMessage:
return &ResizeNodeMessage{}
case messageTypeResizeAbortMessage:
return &ResizeAbortMessage{}
default:
panic(fmt.Sprintf("unknown message type %d", typ))
}
@ -143,18 +148,22 @@ func getMessageType(m Message) byte {
return messageTypeResizeInstruction
case *ResizeInstructionComplete:
return messageTypeResizeInstructionComplete
case *SetCoordinatorMessage:
return messageTypeSetCoordinator
case *UpdateCoordinatorMessage:
return messageTypeUpdateCoordinator
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 *ResizeNodeMessage:
return messageTypeResizeNodeMessage
case *ResizeAbortMessage:
return messageTypeResizeAbortMessage
default:
panic(fmt.Sprintf("don't have type for message %#v", m))
}

283
bsi.go Normal file
View file

@ -0,0 +1,283 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"math/bits"
"github.com/molecula/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
}

159
bsi_test.go Normal file
View file

@ -0,0 +1,159 @@
// Copyright 2021 Molecula Corp. All rights reserved.
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])
}
}
})
}
}

307
cache.go
View file

@ -1,29 +1,19 @@
// 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 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"bytes"
"encoding/json"
"fmt"
"io"
"sort"
"sync"
"time"
"github.com/pilosa/pilosa/v2/lru"
"github.com/pilosa/pilosa/v2/stats"
"github.com/molecula/featurebase/v3/lru"
pb "github.com/molecula/featurebase/v3/proto"
"github.com/molecula/featurebase/v3/stats"
"github.com/pkg/errors"
)
const (
@ -118,7 +108,8 @@ func (c *lruCache) Top() []bitmapPair {
Count: n,
})
}
sort.Sort(bitmapPairs(a))
pairs := bitmapPairs(a)
sort.Sort(&pairs)
return a
}
@ -134,9 +125,11 @@ 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
mu sync.Mutex
entries map[uint64]uint64
rankings bitmapPairs // cached, ordered list
rankingsRead bool
dirty bool
updateN int
updateTime time.Time
@ -168,10 +161,16 @@ func NewRankCache(maxEntries uint32) *rankCache {
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
}
@ -184,11 +183,25 @@ func (c *rankCache) Add(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) {
c.stats.Count(MetricRecalculateCache, 1, 1.0)
c.recalculate()
}
}
// Get returns a count for a given id.
@ -209,12 +222,15 @@ func (c *rankCache) Len() int {
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.
@ -228,7 +244,7 @@ func (c *rankCache) Invalidate() {
func (c *rankCache) Recalculate() {
c.mu.Lock()
defer c.mu.Unlock()
c.stats.Count("cache.recalculate", 1, 1.0)
c.stats.Count(MetricRecalculateCache, 1, 1.0)
c.recalculate()
}
@ -236,27 +252,42 @@ func (c *rankCache) invalidate() {
// Don't invalidate more than once every X seconds.
// TODO: consider making this configurable.
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.
c.stats.Count(MetricInvalidateCacheSkipped, 1, 1.0)
// 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)
c.stats.Count(MetricInvalidateCache, 1, 1.0)
c.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{
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)
c.stats.Gauge(MetricRankCacheLength, float64(length), 1.0)
var removeItems []bitmapPair // cached, ordered list
if length > int(c.maxEntries) {
@ -272,11 +303,14 @@ 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)
c.stats.Count(MetricCacheThresholdReached, 1, 1.0)
for _, pair := range removeItems {
delete(c.entries, pair.ID)
}
}
// The cache is no longer dirty.
c.dirty = false
}
// SetStats defines the stats client used in the cache.
@ -285,7 +319,19 @@ func (c *rankCache) SetStats(s stats.StatsClient) {
}
// 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.
c.stats.Count(MetricReadDirtyCache, 1, 1.0)
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) {
@ -309,17 +355,68 @@ type bitmapPair struct {
// 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,omitempty"`
Key string `json:"key"`
Count uint64 `json:"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,
}
}
// 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
@ -395,6 +492,82 @@ func (p Pairs) String() string {
return buf.String()
}
// PairsField is a Pairs object with its associated field.
type PairsField struct {
Pairs []Pair
Field string
}
func (p *PairsField) Clone() (r *PairsField) {
r = &PairsField{
Pairs: make([]Pair, len(p.Pairs)),
Field: p.Field,
}
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
@ -402,66 +575,6 @@ 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) (*Row, bool)
Add(id uint64, b *Row)
}
// simpleCache implements BitmapCache
// it is meant to be a short-lived cache for cases where writes are continuing to access
// the same row 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]*Row
}
// Fetch retrieves the bitmap at the id in the cache.
func (s *simpleCache) Fetch(id uint64) (*Row, bool) {
m, ok := s.cache[id]
return m, ok
}
// Add adds the bitmap to the cache, keyed on the id. A nil row means
// deleting the row from the cache.
func (s *simpleCache) Add(id uint64, b *Row) {
if b != nil {
s.cache[id] = b
} else {
delete(s.cache, id)
}
}
// nopCache represents a no-op Cache implementation.
type nopCache struct {
stats stats.StatsClient

View file

@ -1,27 +1,15 @@
// 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 2021 Molecula Corp. All rights reserved.
package pilosa_test
import (
"reflect"
"testing"
"github.com/pilosa/pilosa/v2"
"github.com/molecula/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 +19,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
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)
}
}
}

243
catcher.go Normal file
View file

@ -0,0 +1,243 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"github.com/molecula/featurebase/v3/roaring"
txkey "github.com/molecula/featurebase/v3/short_txkey"
"github.com/molecula/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) NewTxIterator(index, field, view string, shard uint64) *roaring.Iterator {
return c.b.NewTxIterator(index, field, view, shard)
}
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) 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) ForEach(index, field, view string, shard uint64, fn func(i uint64) error) error {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see ForEach() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.ForEach(index, field, view, shard, fn)
}
func (c *catcherTx) ForEachRange(index, field, view string, shard uint64, start, end uint64, fn func(uint64) error) error {
defer func() {
if r := recover(); r != nil {
vprint.AlwaysPrintf("see ForEachRange() PanicOn '%v' at '%v'", r, vprint.Stack())
vprint.PanicOn(r)
}
}()
return c.b.ForEachRange(index, field, view, shard, start, end, fn)
}
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) GetSortedFieldViewList(idx *Index, shard uint64) (fvs []txkey.FieldView, err error) {
return c.b.GetSortedFieldViewList(idx, shard)
}
func (tx *catcherTx) GetFieldSizeBytes(index, field string) (uint64, error) {
return 0, nil
}

174
client.go
View file

@ -1,174 +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 (
"context"
"io"
)
// Bit represents the intersection of a row and a column. It can be specified by
// integer ids or string keys.
type Bit struct {
RowID uint64
ColumnID uint64
RowKey string
ColumnKey string
Timestamp int64
}
// FieldValue represents the value for a column within a
// range-encoded field.
type FieldValue struct {
ColumnID uint64
ColumnKey string
Value int64
}
// InternalClient should be implemented by any struct that enables any transport between nodes
// TODO: Refactor
// Note from Travis: Typically an interface containing more than two or three methods is an indication that
// something hasn't been architected correctly.
// While I understand that putting the entire Client behind an interface might require this many methods,
// I don't want to let it go unquestioned.
type InternalClient interface {
MaxShardByIndex(ctx context.Context) (map[string]uint64, error)
Schema(ctx context.Context) ([]*IndexInfo, error)
PostSchema(ctx context.Context, uri *URI, s *Schema, remote bool) error
CreateIndex(ctx context.Context, index string, opt IndexOptions) error
FragmentNodes(ctx context.Context, index string, shard uint64) ([]*Node, error)
Nodes(ctx context.Context) ([]*Node, error)
Query(ctx context.Context, index string, queryRequest *QueryRequest) (*QueryResponse, error)
QueryNode(ctx context.Context, uri *URI, index string, queryRequest *QueryRequest) (*QueryResponse, error)
Import(ctx context.Context, index, field string, shard uint64, bits []Bit, opts ...ImportOption) error
ImportK(ctx context.Context, index, field string, bits []Bit, opts ...ImportOption) error
EnsureIndex(ctx context.Context, name string, options IndexOptions) error
EnsureField(ctx context.Context, indexName string, fieldName string) error
EnsureFieldWithOptions(ctx context.Context, index, field string, opt FieldOptions) error
ImportValue(ctx context.Context, index, field string, shard uint64, vals []FieldValue, opts ...ImportOption) error
ImportValueK(ctx context.Context, index, field string, vals []FieldValue, opts ...ImportOption) error
ExportCSV(ctx context.Context, index, field string, shard uint64, w io.Writer) error
CreateField(ctx context.Context, index, field string) error
CreateFieldWithOptions(ctx context.Context, index, field string, opt FieldOptions) error
FragmentBlocks(ctx context.Context, uri *URI, index, field, view string, shard uint64) ([]FragmentBlock, error)
BlockData(ctx context.Context, uri *URI, index, field, view string, shard uint64, block int) ([]uint64, []uint64, error)
ColumnAttrDiff(ctx context.Context, uri *URI, index string, blks []AttrBlock) (map[uint64]map[string]interface{}, error)
RowAttrDiff(ctx context.Context, uri *URI, index, field string, blks []AttrBlock) (map[uint64]map[string]interface{}, error)
SendMessage(ctx context.Context, uri *URI, msg []byte) error
RetrieveShardFromURI(ctx context.Context, index, field, view string, shard uint64, uri URI) (io.ReadCloser, error)
ImportRoaring(ctx context.Context, uri *URI, index, field string, shard uint64, remote bool, req *ImportRoaringRequest) error
}
//===============
// InternalQueryClient is the internal interface for querying a node.
type InternalQueryClient interface {
QueryNode(ctx context.Context, uri *URI, index string, queryRequest *QueryRequest) (*QueryResponse, error)
}
type nopInternalQueryClient struct{}
func (n *nopInternalQueryClient) QueryNode(ctx context.Context, uri *URI, index string, queryRequest *QueryRequest) (*QueryResponse, error) {
return nil, nil
}
func newNopInternalQueryClient() *nopInternalQueryClient {
return &nopInternalQueryClient{}
}
var _ InternalQueryClient = newNopInternalQueryClient()
//===============
type nopInternalClient struct{}
func newNopInternalClient() nopInternalClient {
return nopInternalClient{}
}
var _ InternalClient = newNopInternalClient()
func (n nopInternalClient) MaxShardByIndex(context.Context) (map[string]uint64, error) {
return nil, nil
}
func (n nopInternalClient) Schema(ctx context.Context) ([]*IndexInfo, error) { return nil, nil }
func (n nopInternalClient) PostSchema(ctx context.Context, uri *URI, s *Schema, remote bool) error {
return nil
}
func (n nopInternalClient) CreateIndex(ctx context.Context, index string, opt IndexOptions) error {
return nil
}
func (n nopInternalClient) FragmentNodes(ctx context.Context, index string, shard uint64) ([]*Node, error) {
return nil, nil
}
func (n nopInternalClient) Nodes(ctx context.Context) ([]*Node, error) {
return nil, nil
}
func (n nopInternalClient) Query(ctx context.Context, index string, queryRequest *QueryRequest) (*QueryResponse, error) {
return nil, nil
}
func (n nopInternalClient) QueryNode(ctx context.Context, uri *URI, index string, queryRequest *QueryRequest) (*QueryResponse, error) {
return nil, nil
}
func (n nopInternalClient) Import(ctx context.Context, index, field string, shard uint64, bits []Bit, opts ...ImportOption) error {
return nil
}
func (n nopInternalClient) ImportK(ctx context.Context, index, field string, bits []Bit, opts ...ImportOption) error {
return nil
}
func (n nopInternalClient) ImportRoaring(ctx context.Context, uri *URI, index, field string, shard uint64, remote bool, req *ImportRoaringRequest) error {
return nil
}
func (n nopInternalClient) EnsureIndex(ctx context.Context, name string, options IndexOptions) error {
return nil
}
func (n nopInternalClient) EnsureField(ctx context.Context, indexName string, fieldName string) error {
return nil
}
func (n nopInternalClient) EnsureFieldWithOptions(ctx context.Context, index, field string, opt FieldOptions) error {
return nil
}
func (n nopInternalClient) ImportValue(ctx context.Context, index, field string, shard uint64, vals []FieldValue, opts ...ImportOption) error {
return nil
}
func (n nopInternalClient) ImportValueK(ctx context.Context, index, field string, vals []FieldValue, opts ...ImportOption) error {
return nil
}
func (n nopInternalClient) ExportCSV(ctx context.Context, index, field string, shard uint64, w io.Writer) error {
return nil
}
func (n nopInternalClient) CreateField(ctx context.Context, index, field string) error { return nil }
func (n nopInternalClient) CreateFieldWithOptions(ctx context.Context, index, field string, opt FieldOptions) error {
return nil
}
func (n nopInternalClient) FragmentBlocks(ctx context.Context, uri *URI, index, field, view string, shard uint64) ([]FragmentBlock, error) {
return nil, nil
}
func (n nopInternalClient) BlockData(ctx context.Context, uri *URI, index, field, view string, shard uint64, block int) ([]uint64, []uint64, error) {
return nil, nil, nil
}
func (n nopInternalClient) ColumnAttrDiff(ctx context.Context, uri *URI, index string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) {
return nil, nil
}
func (n nopInternalClient) RowAttrDiff(ctx context.Context, uri *URI, index, field string, blks []AttrBlock) (map[uint64]map[string]interface{}, error) {
return nil, nil
}
func (n nopInternalClient) SendMessage(ctx context.Context, uri *URI, msg []byte) error {
return nil
}
func (n nopInternalClient) RetrieveShardFromURI(ctx context.Context, index, field, view string, shard uint64, uri URI) (io.ReadCloser, error) {
return nil, nil
}

85
client/README.md Normal file
View file

@ -0,0 +1,85 @@
# Go Client for Pilosa
Go client for Pilosa high performance distributed index.
## Usage
If you have the pilosa repo in your `GOPATH`,
you can import the library in your code using:
```go
import "github.com/pilosa/pilosa/v2/client"
```
### Quick overview
Assuming [Pilosa](https://github.com/pilosa/pilosa) server is running at `localhost:10101` (the default):
```go
package main
import (
"fmt"
"github.com/pilosa/pilosa/v2/client"
)
func main() {
// Create the default client
cli := client.DefaultClient()
// Retrieve the schema
schema, err := cli.Schema()
// Create an Index object
myindex := schema.Index("myindex")
// Create a Field object
myfield := myindex.Field("myfield")
// make sure the index and the field exists on the server
err := cli.SyncSchema(schema)
// Send a Set query. If err is non-nil, response will be nil.
response, err := cli.Query(myfield.Set(5, 42))
// Send a Row query. If err is non-nil, response will be nil.
response, err = cli.Query(myfield.Row(5))
// Get the result
result := response.Result()
// Act on the result
if result != nil {
columns := result.Row().Columns
fmt.Println("Got columns: ", columns)
}
// You can batch queries to improve throughput
response, err = cli.Query(myindex.BatchQuery(
myfield.Row(5),
myfield.Row(10)))
if err != nil {
fmt.Println(err)
}
for _, result := range response.Results() {
// Act on the result
fmt.Println(result.Row().Columns)
}
}
```
## Documentation
### Data Model and Queries
See: [Data Model and Queries](docs/data-model-queries.md)
### Executing Queries
See: [Server Interaction](docs/server-interaction.md)
### Other Documentation
* [Tracing](docs/tracing.md)

1509
client/batch.go Normal file

File diff suppressed because it is too large Load diff

1350
client/batch_test.go Normal file

File diff suppressed because it is too large Load diff

1760
client/client.go Normal file

File diff suppressed because it is too large Load diff

753
client/client_it_test.go Normal file
View file

@ -0,0 +1,753 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
import (
"fmt"
"io/ioutil"
"testing"
"time"
"github.com/molecula/featurebase/v3/disco"
pnet "github.com/molecula/featurebase/v3/net"
"github.com/molecula/featurebase/v3/shardwidth"
"github.com/molecula/featurebase/v3/test"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"
)
var (
testIndex *Index
testIndexWithKeys *Index
testIndexWithKeysNoTrack *Index
testIndexAtomicRecord *Index
testIndexKeyTranslation *Index
testField *Field
testFieldTimeQuantum *Field
testFieldInt0 *Field
testFieldInt1 *Field
)
func setup(t *testing.T, cli *Client) {
t.Helper()
testSchema := NewSchema()
testIndex = testSchema.Index("test-index")
testIndexWithKeys = testSchema.Index("test-index-keys", OptIndexKeys(true))
testIndexWithKeysNoTrack = testSchema.Index("test-index-keys-notrack",
OptIndexKeys(true),
OptIndexTrackExistence(false),
)
testField = testIndex.Field("test-field")
testFieldTimeQuantum = testIndex.Field("test-field-timequantum", OptFieldTypeTime(TimeQuantumYear))
testIndexKeyTranslation = testSchema.Index("test-index-key-translation", OptIndexKeys(true))
testIndexAtomicRecord = testSchema.Index("test-index-atomic-record")
testFieldInt0 = testIndexAtomicRecord.Field("test-field-int0", OptFieldTypeInt(-1000, 1000))
testFieldInt1 = testIndexAtomicRecord.Field("test-field-int1", OptFieldTypeInt(-1000, 1000))
require.NoErrorf(t, cli.SyncSchema(testSchema), "SyncSchema")
}
func tearDown(t *testing.T, cli *Client) {
t.Helper()
for _, i := range []*Index{testIndex, testIndexWithKeys, testIndexWithKeysNoTrack, testIndexAtomicRecord, testIndexKeyTranslation} {
require.NoErrorf(t, cli.DeleteIndex(i), "DeleteIndex(%s)", i.name)
}
}
func TestClientAgainstCluster(t *testing.T) {
for size, replicaN := 3, 1; replicaN <= 2; replicaN++ {
testName := fmt.Sprintf("%d.%d", size, replicaN)
t.Run(testName, func(t *testing.T) {
// Start size.replicaN cluster
c := test.MustNewCluster(t, size)
for _, n := range c.Nodes {
n.Config.Cluster.ReplicaN = replicaN
}
err := c.Start()
require.NoError(t, err, "Start cluster "+testName)
urls := make([]string, len(c.Nodes))
for i, n := range c.Nodes {
urls[i] = n.URL()
}
defer c.Close()
// Create a new client for the cluster
cli, err := newClientFromAddresses(urls, &ClientOptions{})
require.NoErrorf(t, err, "newClientFromAddresses(%v): %v", urls, err)
defer cli.Close()
t.Run("GetStatus", func(t *testing.T) {
status, err := cli.Status()
require.NoErrorf(t, err, "GET /status")
require.Equalf(t, disco.ClusterStateNormal, disco.ClusterState(status.State), "GET /status")
})
t.Run("QueryRow", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
resp, err := cli.Query(testField.Row(1))
require.NoErrorf(t, err, "Query Row")
require.NotNil(t, resp, "Response should not be nil")
})
t.Run("QueryWithShards", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
shardWidth := uint64(1 << shardwidth.Exponent)
_, err := cli.Query(testField.Set(1, 1))
require.NoErrorf(t, err, "Set(1, %d)", 1)
_, err = cli.Query(testField.Set(1, shardWidth))
require.NoErrorf(t, err, "Set(1, %d)", shardWidth)
_, err = cli.Query(testField.Set(1, shardWidth*3))
require.NoErrorf(t, err, "Set(1, %d)", shardWidth*3)
resp, err := cli.Query(testField.Row(1), OptQueryShards(0, 3))
require.NoErrorf(t, err, "Row(1) OptQueryShards(0, 3)")
cols := resp.Result().Row().Columns
require.Equalf(t, []uint64{1, shardWidth * 3}, cols, "Unexpected results: %#v", cols)
})
t.Run("OrmCount", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldCount := testIndex.Field("test-field-count")
err := cli.EnsureField(testFieldCount)
require.NoError(t, err)
qry := testIndex.BatchQuery(
testFieldCount.Set(10, 20),
testFieldCount.Set(10, 21),
testFieldCount.Set(15, 25),
)
_, err = cli.Query(qry)
require.NoErrorf(t, err, "BatchQuery")
resp, err := cli.Query(testIndex.Count(testFieldCount.Row(10)))
require.NoErrorf(t, err, "Count")
require.Equalf(t, int64(2), resp.Result().Count(), "Count")
})
t.Run("DecimalField", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldDec := testIndex.Field("test-field-dec", OptFieldTypeDecimal(3))
err := cli.EnsureField(testFieldDec)
require.NoError(t, err)
sch, err := cli.Schema()
require.NoErrorf(t, err, "Schema")
idx := sch.indexes[testIndex.name]
opts := idx.Field(testFieldDec.name).Options()
require.Equalf(t, int64(3), opts.scale, "%s scale", testFieldDec.name)
})
t.Run("IntersectReturns", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldSegments := testIndex.Field("test-field-segments")
err := cli.EnsureField(testFieldSegments)
require.NoError(t, err)
qry1 := testIndex.BatchQuery(
testFieldSegments.Set(2, 10),
testFieldSegments.Set(2, 15),
testFieldSegments.Set(3, 10),
testFieldSegments.Set(3, 20),
)
_, err = cli.Query(qry1)
require.NoErrorf(t, err, "BatchQuery")
qry2 := testIndex.Intersect(testFieldSegments.Row(2), testFieldSegments.Row(3))
resp, err := cli.Query(qry2)
require.NoErrorf(t, err, "Intersect")
require.Equalf(t, 1, len(resp.Results()), "Intersect number of results")
require.Equalf(t, []uint64{10}, resp.Result().Row().Columns, "Intersect columns results")
})
t.Run("TopNReturns", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldTopN := testIndex.Field("test-field-topn")
err := cli.EnsureField(testFieldTopN)
require.NoError(t, err)
qry := testIndex.BatchQuery(
testFieldTopN.Set(10, 5),
testFieldTopN.Set(10, 10),
testFieldTopN.Set(10, 15),
testFieldTopN.Set(20, 5),
testFieldTopN.Set(30, 5),
)
_, err = cli.Query(qry)
require.NoErrorf(t, err, "BatchQuery")
// XXX: The following is required to make this test pass. See: https://github.com/molecula/featurebase/issues/625
_, _, err = cli.HTTPRequest("POST", "/recalculate-caches", nil, nil)
require.NoErrorf(t, err, "POST /recalculate-caches")
resp, err := cli.Query(testFieldTopN.TopN(2))
require.NoErrorf(t, err, "TopN(2)")
items := resp.Result().CountItems()
require.Equalf(t, 2, len(items), "TopN result CountItems")
item := items[0]
require.Equalf(t, uint64(10), item.ID, "TopN result item[0].ID")
require.Equalf(t, uint64(3), item.Count, "TopN result item[0].Count")
})
t.Run("MinMaxRow", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldMinMax := testIndex.Field("test-field-minmax")
err := cli.EnsureField(testFieldMinMax)
require.NoError(t, err)
qry := testIndex.BatchQuery(
testFieldMinMax.Set(10, 5),
testFieldMinMax.Set(10, 10),
testFieldMinMax.Set(10, 15),
testFieldMinMax.Set(20, 5),
testFieldMinMax.Set(30, 5),
)
_, err = cli.Query(qry)
require.NoErrorf(t, err, "Setting bits")
resp, err := cli.Query(testFieldMinMax.MinRow())
require.NoErrorf(t, err, "MinRow")
min := resp.Result().CountItem().ID
require.Equalf(t, uint64(10), min, "Min")
resp, err = cli.Query(testFieldMinMax.MaxRow())
require.NoErrorf(t, err, "MaxRow")
max := resp.Result().CountItem().ID
require.Equalf(t, uint64(30), max, "Max")
})
t.Run("SetMutexField", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldMutex := testIndex.Field("test-field-mutex", OptFieldTypeMutex(CacheTypeDefault, 0))
err := cli.EnsureField(testFieldMutex)
require.NoError(t, err)
// can set mutex
_, err = cli.Query(testFieldMutex.Set(1, 100))
require.NoErrorf(t, err, "Set(1, 100)")
resp, err := cli.Query(testFieldMutex.Row(1))
require.NoErrorf(t, err, "Row(1)")
target := []uint64{100}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
// setting another row removes the previous
_, err = cli.Query(testFieldMutex.Set(42, 100))
require.NoErrorf(t, err, "Set(42, 100)")
resp, err = cli.Query(testIndex.BatchQuery(
testFieldMutex.Row(1),
testFieldMutex.Row(42),
))
require.NoErrorf(t, err, "BatchQuery")
target1 := []uint64(nil)
target42 := []uint64{100}
require.Equalf(t, target1, resp.Results()[0].Row().Columns, "Row Results[0] Columns")
require.Equalf(t, target42, resp.Results()[1].Row().Columns, "Row Results[1] Columns")
})
t.Run("SetBoolField", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldBool := testIndex.Field("test-field-bool", OptFieldTypeBool())
err := cli.EnsureField(testFieldBool)
require.NoError(t, err)
// can set bool
_, err = cli.Query(testFieldBool.Set(true, 100))
require.NoErrorf(t, err, "Set(true, 100)")
resp, err := cli.Query(testFieldBool.Row(true))
require.NoErrorf(t, err, "Row(true)")
target := []uint64{100}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
})
t.Run("ClearRowQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldClear := testIndex.Field("test-field-clear")
err := cli.EnsureField(testFieldClear)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldClear.Set(1, 100),
testFieldClear.Set(1, 200),
))
require.NoErrorf(t, err, "Set(1, 100) Set(1, 200)")
resp, err := cli.Query(testFieldClear.Row(1))
require.NoErrorf(t, err, "Row(1)")
target := []uint64{100, 200}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
_, err = cli.Query(testFieldClear.ClearRow(1))
require.NoErrorf(t, err, "ClearRow(1)")
resp, err = cli.Query(testFieldClear.Row(1))
require.NoErrorf(t, err, "Row(1)")
target = []uint64(nil)
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
})
t.Run("RowsQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldRows := testIndex.Field("test-field-rows")
err := cli.EnsureField(testFieldRows)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldRows.Set(1, 100),
testFieldRows.Set(1, 200),
testFieldRows.Set(2, 200),
))
require.NoErrorf(t, err, "Set(1, 100) Set(1, 200) Set(2, 200)")
resp, err := cli.Query(testFieldRows.Rows())
require.NoErrorf(t, err, "Rows")
target := RowIdentifiersResult{
IDs: []uint64{1, 2},
}
require.Equalf(t, target, resp.Result().RowIdentifiers(), "RowIdentifiers Result")
})
t.Run("UnionRowsQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldRows := testIndex.Field("test-field-rows")
err := cli.EnsureField(testFieldRows)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldRows.Set(1, 100),
testFieldRows.Set(1, 200),
testFieldRows.Set(2, 200),
))
require.NoErrorf(t, err, "Set(1, 100) Set(1, 200) Set(2, 200)")
resp, err := cli.Query(testFieldRows.Rows().Union())
require.NoErrorf(t, err, "Rows Union")
target := []uint64{100, 200}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
})
t.Run("LikeQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldLike := testIndex.Field("test-field-like", OptFieldKeys(true))
err := cli.EnsureField(testFieldLike)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldLike.Set("a", 100),
testFieldLike.Set("b", 200),
testFieldLike.Set("bc", 200),
))
require.NoErrorf(t, err, "Set(a, 100) Set(b, 200) Set(bc, 200)")
resp, err := cli.Query(testFieldLike.Like("b%"))
require.NoErrorf(t, err, `Like(b%)`)
target := RowIdentifiersResult{
Keys: []string{"b", "bc"},
}
require.Equalf(t, target, resp.Result().RowIdentifiers(), "RowIdentifiers Result")
})
t.Run("GroupByQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldGroupBy := testIndex.Field("test-field-group-by")
err := cli.EnsureField(testFieldGroupBy)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldGroupBy.Set(1, 100),
testFieldGroupBy.Set(1, 200),
testFieldGroupBy.Set(2, 200),
))
require.NoErrorf(t, err, "Set(1, 100) Set(1, 200) Set(2, 200)")
resp, err := cli.Query(testIndex.GroupBy(testFieldGroupBy.Rows()))
require.NoErrorf(t, err, `Like(b%)`)
target := []GroupCount{
{Groups: []FieldRow{{FieldName: "test-field-group-by", RowID: 1}}, Count: 2},
{Groups: []FieldRow{{FieldName: "test-field-group-by", RowID: 2}}, Count: 1},
}
assertGroupBy(t, target, resp.Result().GroupCounts())
})
t.Run("GroupByQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldGroupBy := testIndex.Field("test-field-group-by-int", OptFieldTypeInt(-10, 10))
err := cli.EnsureField(testFieldGroupBy)
require.NoError(t, err)
_, err = cli.Query(testIndex.RawQuery(`
Set(0, test-field-group-by-int=1)
Set(1, test-field-group-by-int=2)
Set(2, test-field-group-by-int=-2)
Set(3, test-field-group-by-int=-1)
Set(4, test-field-group-by-int=4)
Set(10, test-field-group-by-int=0)
Set(100, test-field-group-by-int=0)
Set(1000, test-field-group-by-int=0)
Set(10000, test-field-group-by-int=0)
Set(100000, test-field-group-by-int=0)
`))
require.NoError(t, err, "Set(0..100000)")
resp, err := cli.Query(testIndex.GroupBy(testFieldGroupBy.Rows()))
require.NoErrorf(t, err, `GroupBy(Rows)`)
var a, b, c, d, e, f int64 = -2, -1, 0, 1, 2, 4
target := []GroupCount{
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &a}}, Count: 1},
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &b}}, Count: 1},
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &c}}, Count: 5},
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &d}}, Count: 1},
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &e}}, Count: 1},
{Groups: []FieldRow{{FieldName: "test-field-group-by-int", Value: &f}}, Count: 1},
}
assertGroupBy(t, target, resp.Result().GroupCounts())
})
t.Run("CreateDeleteIndexField", func(t *testing.T) {
tmpIndex := NewIndex("tmp-index")
tmpField := tmpIndex.Field("tmp-field")
err := cli.CreateIndex(tmpIndex)
require.NoError(t, err)
err = cli.CreateField(tmpField)
require.NoError(t, err)
err = cli.DeleteField(tmpField)
require.NoError(t, err)
err = cli.DeleteIndex(tmpIndex)
require.NoError(t, err)
})
t.Run("ErrorCreatingIndexField", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
require.ErrorIs(t, cli.CreateIndex(testIndex), ErrIndexExists)
require.ErrorIs(t, cli.CreateField(testField), ErrFieldExists)
})
t.Run("Failover", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
uri, _ := pnet.NewURIFromAddress("does-not-resolve.foo.bar")
tmpcli, _ := NewClient(NewClusterWithHost(uri, uri, uri, uri), OptClientRetries(0))
_, err := tmpcli.Query(testIndex.All())
require.Error(t, err, ErrTriedMaxHosts)
})
t.Run("InvalidQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
_, _, err := cli.HTTPRequest("INVALID METHOD", "/foo", nil, nil)
require.Error(t, err)
_, err = cli.Query(testIndex.RawQuery("Invalid query"))
require.Error(t, err)
})
t.Run("Sync", func(t *testing.T) {
testIndexRemote := NewIndex("test-index-remote")
err := cli.EnsureIndex(testIndexRemote)
require.NoError(t, err)
testFieldRemote := testIndexRemote.Field("test-field-remote")
err = cli.EnsureField(testFieldRemote)
require.NoError(t, err)
schema := NewSchema()
idx1 := schema.Index("index-1")
idx1.Field("field-1-1")
idx1.Field("field-1-2")
idx2 := schema.Index("index-2")
idx2.Field("field-2-1")
schema.Index(testIndexRemote.Name())
err = cli.SyncSchema(schema)
require.NoError(t, err)
err = cli.DeleteIndex(testIndexRemote)
require.NoError(t, err)
err = cli.DeleteIndex(idx1)
require.NoError(t, err)
err = cli.DeleteIndex(idx2)
require.NoError(t, err)
})
t.Run("FetchFragmentNodes", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
nodes, err := cli.fetchFragmentNodes(testIndex.Name(), 0)
require.NoErrorf(t, err, "fetchFragmentNodes(%s, 0)", testIndex.name)
require.Equalf(t, replicaN, len(nodes), "len(nodes)")
// running the same for coverage
nodes, err = cli.fetchFragmentNodes(testIndex.Name(), 0)
require.NoErrorf(t, err, "fetchFragmentNodes(%s, 0)", testIndex.name)
require.Equalf(t, replicaN, len(nodes), "len(nodes)")
})
t.Run("RowRangeQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldRange := testIndex.Field("test-field-range", OptFieldTypeTime(TimeQuantumMonthDayHour))
err := cli.EnsureField(testFieldRange)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldRange.SetTimestamp(10, 100, time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)),
testFieldRange.SetTimestamp(10, 100, time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)),
testFieldRange.SetTimestamp(10, 100, time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),
))
require.NoErrorf(t, err, "BatchQuery SetTimestamp")
start := time.Date(2017, time.January, 5, 0, 0, 0, 0, time.UTC)
end := time.Date(2018, time.January, 5, 0, 0, 0, 0, time.UTC)
resp, err := cli.Query(testFieldRange.RowRange(10, start, end))
require.NoErrorf(t, err, "RowRange(10, %v, %v)", start, end)
target := []uint64{100}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
})
t.Run("StoreQuery", func(t *testing.T) {
schema := NewSchema()
testIndexStore := schema.Index("test-index-store")
testFieldFrom := testIndexStore.Field("test-field-from")
testFieldTo := testIndexStore.Field("test-field-to")
err := cli.SyncSchema(schema)
require.NoError(t, err)
defer func() {
cerr := cli.DeleteIndex(testIndexStore)
require.NoErrorf(t, cerr, "failed to delete index: %v", testIndexStore.name)
}()
_, err = cli.Query(testIndexStore.BatchQuery(
testFieldFrom.Set(10, 100),
testFieldFrom.Set(10, 200),
testFieldTo.Store(testFieldFrom.Row(10), 1),
))
require.NoErrorf(t, err, "Set(10, 100) Set(10, 200) Store(Row(10), 1)")
resp, err := cli.Query(testFieldTo.Row(1))
require.NoErrorf(t, err, "Row(1)")
target := []uint64{100, 200}
require.Equalf(t, target, resp.Result().Row().Columns, "Row Result Columns")
})
t.Run("MultipleClientKeyQuery", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldMultiClient := testIndexWithKeys.Field("test-field-multiclient")
err := cli.EnsureField(testFieldMultiClient)
require.NoError(t, err)
eg := &errgroup.Group{}
for i := 0; i < 10; i++ {
rowID := uint64(i)
eg.Go(func() error {
_, e := cli.Query(testFieldMultiClient.Set(rowID, "col"))
return e
})
}
require.NoError(t, eg.Wait())
})
t.Run("ExportRowIDColumnID", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldExport := testIndex.Field("test-field-export")
err := cli.EnsureField(testFieldExport)
require.NoError(t, err)
_, err = cli.Query(testIndex.BatchQuery(
testFieldExport.Set(1, 1),
testFieldExport.Set(1, 10),
testFieldExport.Set(2, 1048577),
), nil)
require.NoErrorf(t, err, "Set(1, 1) Set(1, 10) Set(2, 1048577)")
r, err := cli.ExportField(testFieldExport)
require.NoErrorf(t, err, "ExportField")
b, err := ioutil.ReadAll(r)
require.NoError(t, err)
target := "1,1\n1,10\n2,1048577\n"
require.Equalf(t, target, string(b), "Export Field Response")
})
t.Run("ExportRowIDColumnKey", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldExport := testIndexWithKeys.Field("test-field-export")
err := cli.EnsureField(testFieldExport)
require.NoError(t, err)
_, err = cli.Query(testIndexWithKeys.BatchQuery(
testFieldExport.Set(1, "one"),
testFieldExport.Set(1, "ten"),
testFieldExport.Set(2, "big-number"),
), nil)
require.NoErrorf(t, err, "Set(1, one) Set(1, ten) Set(2, big-number)")
r, err := cli.ExportField(testFieldExport)
require.NoErrorf(t, err, "ExportField")
b, err := ioutil.ReadAll(r)
require.NoError(t, err)
target := "1,one\n1,ten\n2,big-number\n"
require.Equalf(t, target, string(b), "Export Field Response")
})
t.Run("TranslateRowKeys", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
testFieldTranslate := testIndexKeyTranslation.Field("test-field-translate", OptFieldKeys(true))
err := cli.EnsureField(testFieldTranslate)
require.NoError(t, err)
trans, err := cli.CreateFieldKeys(testFieldTranslate, "key1", "key2")
require.NoErrorf(t, err, "CreateFieldKeys")
target := map[string]uint64{"key1": 1, "key2": 2}
require.Equalf(t, target, trans, "CreateFieldKeys")
trans, err = cli.FindFieldKeys(testFieldTranslate, "key1", "key2", "key3")
require.NoErrorf(t, err, "FindFieldKeys")
require.Equalf(t, target, trans, "FindFieldKeys")
})
t.Run("TranslateColKeys", func(t *testing.T) {
setup(t, cli)
defer tearDown(t, cli)
created, err := cli.CreateIndexKeys(testIndexKeyTranslation, "key1", "key2")
require.NoErrorf(t, err, "CreateIndexKeys")
if _, ok := created["key1"]; !ok {
t.Error("key1 missing")
}
if _, ok := created["key2"]; !ok {
t.Error("key2 missing")
}
found, err := cli.FindIndexKeys(testIndexKeyTranslation, "key1", "key2", "key3")
require.NoErrorf(t, err, "FindIndexKeys")
require.Equalf(t, created, found, "IndexKeys")
})
t.Run("Transactions", func(t *testing.T) {
trns, err := cli.StartTransaction("blah", time.Minute, false, time.Minute)
require.NoErrorf(t, err, "StartTransaction(blah)")
require.Equalf(t, "blah", trns.ID, "TranslateColumnKeys ID")
require.Equalf(t, time.Minute, trns.Timeout, "TranslateColumnKeys Timeout")
require.Truef(t, trns.Active, "TranslateColumnKeys Active")
trnsMap, err := cli.Transactions()
require.NoErrorf(t, err, "Transactions")
require.Equalf(t, 1, len(trnsMap), "Transactions len")
require.Truef(t, trnsMap["blah"].Active, "Transactions Active")
trns, err = cli.GetTransaction("blah")
require.NoErrorf(t, err, "GetTransaction(blah)")
require.Equalf(t, "blah", trns.ID, "TranslateColumnKeys ID")
require.Equalf(t, time.Minute, trns.Timeout, "TranslateColumnKeys Timeout")
require.Truef(t, trns.Active, "TranslateColumnKeys Active")
trns, err = cli.FinishTransaction("blah")
require.NoErrorf(t, err, "FinishTransaction(blah)")
require.Equalf(t, "blah", trns.ID, "TranslateColumnKeys ID")
require.Equalf(t, time.Minute, trns.Timeout, "TranslateColumnKeys Timeout")
require.Truef(t, trns.Active, "TranslateColumnKeys Active")
})
})
}
}
func assertGroupBy(t *testing.T, expected, results []GroupCount) {
t.Helper()
require.Equalf(t, len(expected), len(results), "number of groupings mismatch")
for i, result := range results {
require.Equalf(t, expected[i], result, "unexpected result at %d", i)
}
}

209
client/client_test.go Normal file
View file

@ -0,0 +1,209 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"crypto/tls"
"errors"
"reflect"
"testing"
pnet "github.com/molecula/featurebase/v3/net"
)
func TestQueryWithError(t *testing.T) {
var err error
client := DefaultClient()
index := NewIndex("foo")
invalid := NewPQLRowQuery("", index, errors.New("invalid"))
_, err = client.Query(invalid, nil)
if err == nil {
t.Fatalf("Should have failed")
}
}
func TestClientOptions(t *testing.T) {
targets := []*ClientOptions{
{SocketTimeout: 10},
{ConnectTimeout: 5},
{PoolSizePerRoute: 7},
{TotalPoolSize: 17},
{TLSConfig: &tls.Config{InsecureSkipVerify: true}},
}
optionsList := [][]ClientOption{
{OptClientSocketTimeout(10)},
{OptClientConnectTimeout(5)},
{OptClientPoolSizePerRoute(7)},
{OptClientTotalPoolSize(17)},
{OptClientTLSConfig(&tls.Config{InsecureSkipVerify: true})},
}
for i := 0; i < len(targets); i++ {
options := &ClientOptions{}
err := options.addOptions(optionsList[i]...)
if err != nil {
t.Fatal(err)
}
target := targets[i]
if !reflect.DeepEqual(target, options) {
t.Fatalf("%v != %v", target, options)
}
}
}
func TestNewClientWithErrorredOption(t *testing.T) {
_, err := NewClient(":8888", ClientOptionErr(0))
if err == nil {
t.Fatalf("Should have failed")
}
}
func TestNewClient(t *testing.T) {
client, err := NewClient(":9999", OptClientManualServerAddress(true))
if err != nil {
t.Fatal(err)
}
targetURI, err := pnet.NewURIFromAddress(":9999")
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(targetURI, client.manualServerURI) {
t.Fatalf("%v != %v", targetURI, client.manualServerURI)
}
targetFragmentNode := &fragmentNode{
Scheme: "http",
Host: "localhost",
Port: 9999,
}
if !reflect.DeepEqual(targetFragmentNode, client.manualFragmentNode) {
t.Fatalf("%v != %v", targetFragmentNode, client.manualFragmentNode)
}
client, err = NewClient(":9999")
if err != nil {
t.Fatal(err)
}
targetURI, err = pnet.NewURIFromAddress(":9999")
if err != nil {
t.Fatal(err)
}
target := []*pnet.URI{targetURI}
if !reflect.DeepEqual(target, client.cluster.hosts) {
t.Fatalf("%v != %v", target, client.cluster.hosts)
}
client, err = NewClient([]string{":9999"})
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(target, client.cluster.hosts) {
t.Fatalf("%v != %v", target, client.cluster.hosts)
}
targetURI1, err := pnet.NewURIFromAddress(":8888")
if err != nil {
t.Fatal(err)
}
targetURI2, err := pnet.NewURIFromAddress(":9999")
if err != nil {
t.Fatal(err)
}
client, err = NewClient([]*pnet.URI{targetURI1, targetURI2})
if err != nil {
t.Fatal(err)
}
target = []*pnet.URI{targetURI1, targetURI2}
if !reflect.DeepEqual(target, client.cluster.hosts) {
t.Fatalf("%v != %v", target, client.cluster.hosts)
}
client, err = NewClient([]*pnet.URI{targetURI})
if err != nil {
t.Fatal(err)
}
target = []*pnet.URI{targetURI}
if !reflect.DeepEqual(target, client.cluster.hosts) {
t.Fatalf("%v != %v", target, client.cluster.hosts)
}
client, err = NewClient(DefaultCluster())
if err != nil {
t.Fatal(err)
}
target = []*pnet.URI{}
if !reflect.DeepEqual(target, client.cluster.hosts) {
t.Fatalf("%v != %v", target, client.cluster.hosts)
}
}
func TestNewClientWithInvalidAddr(t *testing.T) {
_, err := NewClient(10)
if err != ErrAddrURIClusterExpected {
t.Fatalf("%v != %v", ErrAddrURIClusterExpected, err)
}
_, err = NewClient(":invalid")
if err == nil {
t.Fatalf("should have failed: %+v", err)
}
_, err = NewClient([]string{"valid:8000", ":invalid"})
if err != pnet.ErrInvalidAddress {
t.Fatalf("Should have failed '%v, got '%v'", pnet.ErrInvalidAddress, err)
}
}
func TestNewClientManualAddressWithNoURIs(t *testing.T) {
_, err := NewClient([]string{}, OptClientManualServerAddress(true))
if err != ErrSingleServerAddressRequired {
t.Fatalf("%v != %v", ErrSingleServerAddressRequired, err)
}
_, err = NewClient([]*pnet.URI{}, OptClientManualServerAddress(true))
if err != ErrSingleServerAddressRequired {
t.Fatalf("%v != %v", ErrSingleServerAddressRequired, err)
}
}
func TestNewClientManualAddressWithMultipleURIs(t *testing.T) {
_, err := NewClient([]string{":9000", ":5000"}, OptClientManualServerAddress(true))
if err != ErrSingleServerAddressRequired {
t.Fatalf("%v != %v", ErrSingleServerAddressRequired, err)
}
targetURI1, err := pnet.NewURIFromAddress(":9000")
if err != nil {
t.Fatal(err)
}
targetURI2, err := pnet.NewURIFromAddress(":5000")
if err != nil {
t.Fatal(err)
}
_, err = NewClient([]*pnet.URI{targetURI1, targetURI2}, OptClientManualServerAddress(true))
if err != ErrSingleServerAddressRequired {
t.Fatalf("%v != %v", ErrSingleServerAddressRequired, err)
}
}
func ClientOptionErr(int) ClientOption {
return func(*ClientOptions) error {
return errors.New("Some error")
}
}
func TestQueryOptionsError(t *testing.T) {
client := DefaultClient()
index := NewIndex("foo")
_, err := client.Query(index.RawQuery(""), QueryOptionErr(0))
if err == nil {
t.Fatalf("should have failed")
}
}
func QueryOptionErr(int) QueryOption {
return func(*QueryOptions) error {
return errors.New("Some error")
}
}

99
client/cluster.go Normal file
View file

@ -0,0 +1,99 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"sync"
pnet "github.com/molecula/featurebase/v3/net"
)
// Cluster contains hosts in a Pilosa cluster.
type Cluster struct {
hosts []*pnet.URI
okList []bool
mutex *sync.RWMutex
lastHostIdx int
}
// DefaultCluster returns the default Cluster.
func DefaultCluster() *Cluster {
return &Cluster{
hosts: make([]*pnet.URI, 0),
okList: make([]bool, 0),
mutex: &sync.RWMutex{},
}
}
// NewClusterWithHost returns a cluster with the given URIs.
func NewClusterWithHost(hosts ...*pnet.URI) *Cluster {
cluster := DefaultCluster()
for _, host := range hosts {
cluster.AddHost(host)
}
return cluster
}
// AddHost adds a host to the cluster.
func (c *Cluster) AddHost(address *pnet.URI) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.hosts = append(c.hosts, address)
c.okList = append(c.okList, true)
}
// Host returns a host in the cluster.
func (c *Cluster) Host() *pnet.URI {
c.mutex.Lock()
var host *pnet.URI
for i := range c.okList {
idx := (i + c.lastHostIdx) % len(c.okList)
ok := c.okList[idx]
if ok {
host = c.hosts[idx]
break
}
}
c.lastHostIdx++
c.mutex.Unlock()
if host != nil {
return host
}
c.reset()
return host
}
// RemoveHost black lists the host with the given pnet.URI from the cluster.
func (c *Cluster) RemoveHost(address *pnet.URI) {
c.mutex.Lock()
defer c.mutex.Unlock()
for i, uri := range c.hosts {
if uri.Equals(address) {
c.okList[i] = false
break
}
}
}
// Hosts returns all available hosts in the cluster.
func (c *Cluster) Hosts() []pnet.URI {
c.mutex.RLock()
defer c.mutex.RUnlock()
hosts := make([]pnet.URI, 0, len(c.hosts))
for i, host := range c.hosts {
if c.okList[i] {
hosts = append(hosts, *host)
}
}
return hosts
}
func (c *Cluster) reset() {
c.mutex.Lock()
defer c.mutex.Unlock()
for i := range c.okList {
c.okList[i] = true
}
}

70
client/cluster_test.go Normal file
View file

@ -0,0 +1,70 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"testing"
pnet "github.com/molecula/featurebase/v3/net"
)
func TestNewClusterWithHost(t *testing.T) {
c := NewClusterWithHost(pnet.DefaultURI())
hosts := c.Hosts()
if len(hosts) != 1 || !hosts[0].Equals(pnet.DefaultURI()) {
t.Fail()
}
}
func TestAddHost(t *testing.T) {
const addr = "http://localhost:3000"
c := DefaultCluster()
if c.Hosts() == nil {
t.Fatalf("Hosts should not be nil")
}
uri, err := pnet.NewURIFromAddress(addr)
if err != nil {
t.Fatalf("Cannot parse address")
}
target, err := pnet.NewURIFromAddress(addr)
if err != nil {
t.Fatalf("Cannot parse address")
}
c.AddHost(uri)
hosts := c.Hosts()
if len(hosts) != 1 || !hosts[0].Equals(target) {
t.Fail()
}
}
func TestHosts(t *testing.T) {
c := DefaultCluster()
if c.Host() != nil {
t.Fatalf("Hosts with empty cluster should return nil")
}
c = NewClusterWithHost(pnet.DefaultURI())
if !c.Host().Equals(pnet.DefaultURI()) {
t.Fatalf("Host should return a value if there are hosts in the cluster")
}
}
func TestRemoveHost(t *testing.T) {
uri, err := pnet.NewURIFromAddress("index1.pilosa.com:9999")
if err != nil {
t.Fatal(err)
}
c := NewClusterWithHost(uri)
if len(c.hosts) != 1 {
t.Fatalf("The cluster should contain the host")
}
uri, err = pnet.NewURIFromAddress("index1.pilosa.com:9999")
if err != nil {
t.Fatal(err)
}
c.RemoveHost(uri)
if len(c.Hosts()) != 0 {
t.Fatalf("The cluster should not contain the host")
}
}

181
client/csv/csv.go Normal file
View file

@ -0,0 +1,181 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package csv
import (
"bufio"
"errors"
"fmt"
"io"
"strconv"
"strings"
"time"
"github.com/molecula/featurebase/v3/client"
)
// Format is the format of the data in the CSV file.
type Format uint
const (
// RowIDColumnID formatted data is ROW_ID,COLUMN_ID.
RowIDColumnID Format = iota
// RowIDColumnKey formatted data is ROW_ID,COLUMN_KEY.
RowIDColumnKey
// RowKeyColumnID formatted data is ROW_KEY,COLUMN_ID.
RowKeyColumnID
// RowKeyColumnKey formatted data is ROW_KEY,COLUMN_ID.
RowKeyColumnKey
// ColumnID formatted data is COLUMN_ID. Valid only for value import.
ColumnID
// ColumnKey formatted data is COLUMN_KEY. Valud only for value import.
ColumnKey
)
// ColumnUnmarshaller creates a RecordUnmarshaller for importing columns with the given format.
func ColumnUnmarshaller(format Format) RecordUnmarshaller {
return ColumnUnmarshallerWithTimestamp(format, "")
}
// ColumnUnmarshallerWithTimestamp creates a RecordUnmarshaller for importing columns with the given format and timestamp format.
func ColumnUnmarshallerWithTimestamp(format Format, timestampFormat string) RecordUnmarshaller {
return func(text string) (client.Record, error) {
var err error
column := client.Column{}
parts := strings.Split(text, ",")
if len(parts) < 2 {
return nil, errors.New("invalid CSV line")
}
hasRowKey := format == RowKeyColumnID || format == RowKeyColumnKey
hasColumnKey := format == RowIDColumnKey || format == RowKeyColumnKey
if hasRowKey {
column.RowKey = parts[0]
} else {
column.RowID, err = strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, errors.New("invalid row ID")
}
}
if hasColumnKey {
column.ColumnKey = parts[1]
} else {
column.ColumnID, err = strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return nil, errors.New("invalid column ID")
}
}
timestamp := int64(0)
if len(parts) == 3 {
if timestampFormat == "" {
if tsInt, err := strconv.Atoi(parts[2]); err != nil {
return nil, err
} else {
timestamp = int64(tsInt)
}
} else {
t, err := time.Parse(timestampFormat, parts[2])
if err != nil {
return nil, err
}
timestamp = t.Unix() * int64(time.Second) // Casting a duration to int64 gives the number of nanoseconds in that duration.
}
}
column.Timestamp = timestamp
return column, nil
}
}
// RecordUnmarshaller is a function which creates a Record from a CSV file line with column data.
type RecordUnmarshaller func(text string) (client.Record, error)
// Iterator reads records from a Reader.
// Each line should contain a single record in the following form:
// field1,field2,...
type Iterator struct {
reader io.Reader
line int
scanner *bufio.Scanner
unmarshaller RecordUnmarshaller
}
// NewIterator creates a CSVIterator from a Reader.
func NewIterator(reader io.Reader, unmarshaller RecordUnmarshaller) *Iterator {
return &Iterator{
reader: reader,
line: 0,
scanner: bufio.NewScanner(reader),
unmarshaller: unmarshaller,
}
}
// NewColumnIterator creates a new iterator for column data.
func NewColumnIterator(format Format, reader io.Reader) *Iterator {
return NewIterator(reader, ColumnUnmarshaller(format))
}
// NewColumnIteratorWithTimestampFormat creates a new iterator for column data with timestamp.
func NewColumnIteratorWithTimestampFormat(format Format, reader io.Reader, timestampFormat string) *Iterator {
return NewIterator(reader, ColumnUnmarshallerWithTimestamp(format, timestampFormat))
}
// NewValueIterator creates a new iterator for value data.
func NewValueIterator(format Format, reader io.Reader) *Iterator {
return NewIterator(reader, FieldValueUnmarshaller(format))
}
// NextRecord iterates on lines of a Reader.
// Returns io.EOF on end of iteration.
func (c *Iterator) NextRecord() (client.Record, error) {
if ok := c.scanner.Scan(); ok {
c.line++
text := strings.TrimSpace(c.scanner.Text())
if text != "" {
rc, err := c.unmarshaller(text)
if err != nil {
return nil, fmt.Errorf("%s at line: %d", err.Error(), c.line)
}
return rc, nil
}
}
err := c.scanner.Err()
if err != nil {
return nil, err
}
return nil, io.EOF
}
// FieldValueUnmarshaller is a function which creates a Record from a CSV file line with value data.
func FieldValueUnmarshaller(format Format) RecordUnmarshaller {
return func(text string) (client.Record, error) {
parts := strings.Split(text, ",")
if len(parts) < 2 {
return nil, errors.New("invalid CSV")
}
value, err := strconv.ParseInt(parts[1], 10, 64)
if err != nil {
return nil, errors.New("invalid value")
}
switch format {
case ColumnID:
columnID, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, errors.New("invalid column ID at line: %d")
}
return client.FieldValue{
ColumnID: uint64(columnID),
Value: value,
}, nil
case ColumnKey:
return client.FieldValue{
ColumnKey: parts[0],
Value: value,
}, nil
default:
return nil, fmt.Errorf("invalid format: %d", format)
}
}
}

48
client/csv/csv_it_test.go Normal file
View file

@ -0,0 +1,48 @@
// Copyright 2021 Molecula Corp. All rights reserved.
//go:build integration
// +build integration
package csv_test
import (
"io"
"reflect"
"strings"
"testing"
"github.com/molecula/featurebase/v3/client"
"github.com/molecula/featurebase/v3/client/csv"
)
func TestCSVIterate(t *testing.T) {
text := `10,7
10,5
2,3
7,1`
iterator := csv.NewColumnIterator(csv.RowIDColumnID, strings.NewReader(text))
recs := consumeIterator(t, iterator)
target := []client.Record{
client.Column{RowID: 10, ColumnID: 7},
client.Column{RowID: 10, ColumnID: 5},
client.Column{RowID: 2, ColumnID: 3},
client.Column{RowID: 7, ColumnID: 1},
}
if !reflect.DeepEqual(target, recs) {
t.Fatalf("%v != %v", target, recs)
}
}
func consumeIterator(t *testing.T, it *csv.Iterator) []client.Record {
recs := []client.Record{}
for {
r, err := it.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
recs = append(recs, r)
}
return recs
}

254
client/csv/csv_test.go Normal file
View file

@ -0,0 +1,254 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package csv_test
import (
"errors"
"io"
"reflect"
"strings"
"testing"
"github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/client"
"github.com/molecula/featurebase/v3/client/csv"
)
func TestCSVColumnIterator(t *testing.T) {
reader := strings.NewReader(`1,10,683793200
5,20,683793300
3,41,683793385`)
iterator := csv.NewColumnIterator(csv.RowIDColumnID, reader)
columns := []client.Record{}
for {
column, err := iterator.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
columns = append(columns, column)
}
if len(columns) != 3 {
t.Fatalf("There should be 3 columns")
}
target := []client.Column{
{RowID: 1, ColumnID: 10, Timestamp: 683793200},
{RowID: 5, ColumnID: 20, Timestamp: 683793300},
{RowID: 3, ColumnID: 41, Timestamp: 683793385},
}
for i := range target {
if !reflect.DeepEqual(target[i], columns[i]) {
t.Fatalf("%v != %v", target[i], columns[i])
}
}
}
func TestCSVColumnIteratorWithTimestampFormatRowIDColumnID(t *testing.T) {
format := "2006-01-02T03:04"
reader := strings.NewReader(`1,10,1991-09-02T09:33
5,20,1991-09-02T09:35
3,41,1991-09-02T09:36`)
iterator := csv.NewColumnIteratorWithTimestampFormat(csv.RowIDColumnID, reader, format)
records := []client.Record{}
for {
record, err := iterator.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
records = append(records, record)
}
target := []client.Column{
{RowID: 1, ColumnID: 10, Timestamp: 683803980000000000},
{RowID: 5, ColumnID: 20, Timestamp: 683804100000000000},
{RowID: 3, ColumnID: 41, Timestamp: 683804160000000000},
}
if len(records) != len(target) {
t.Fatalf("There should be %d columns", len(target))
}
for i := range target {
if !reflect.DeepEqual(target[i], records[i]) {
t.Fatalf("%v != %v", target[i], records[i])
}
}
}
func TestCSVColumnIteratorWithTimestampFormatRowKeyColumnKey(t *testing.T) {
format := "2006-01-02T03:04"
reader := strings.NewReader(`one,ten,1991-09-02T09:33
five,twenty,1991-09-02T09:35
three,forty-one,1991-09-02T09:36`)
iterator := csv.NewColumnIteratorWithTimestampFormat(csv.RowKeyColumnKey, reader, format)
records := []client.Record{}
for {
record, err := iterator.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
records = append(records, record)
}
target := []client.Column{
{RowKey: "one", ColumnKey: "ten", Timestamp: 683803980000000000},
{RowKey: "five", ColumnKey: "twenty", Timestamp: 683804100000000000},
{RowKey: "three", ColumnKey: "forty-one", Timestamp: 683804160000000000},
}
if len(records) != len(target) {
t.Fatalf("There should be %d columns", len(target))
}
for i := range target {
if !reflect.DeepEqual(target[i], records[i]) {
t.Fatalf("%v != %v", target[i], records[i])
}
}
}
func TestCSVColumnIteratorWithTimestampFormatFail(t *testing.T) {
format := "2014-07-16"
reader := strings.NewReader(`1,10,X`)
iterator := csv.NewColumnIteratorWithTimestampFormat(csv.RowIDColumnID, reader, format)
_, err := iterator.NextRecord()
if err == nil {
t.Fatalf("Should have failed")
}
}
func TestCSVValueIteratorWithColumnID(t *testing.T) {
reader := strings.NewReader(`1,10
5,-20
3,41
`)
iterator := csv.NewValueIterator(csv.ColumnID, reader)
values := []client.Record{}
for {
value, err := iterator.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
values = append(values, value)
}
target := []pilosa.FieldValue{
{ColumnID: 1, Value: 10},
{ColumnID: 5, Value: -20},
{ColumnID: 3, Value: 41},
}
if len(values) != len(target) {
t.Fatalf("There should be %d values, got %d", len(target), len(values))
}
for i := range target {
v := values[i].(client.FieldValue)
if !reflect.DeepEqual(pilosa.FieldValue(v), target[i]) {
t.Fatalf("'%+v' != '%+v'", target[i], values[i])
}
}
}
func TestCSVValueIteratorWithColumnKey(t *testing.T) {
reader := strings.NewReader(`one,10
five,-20
three,41
`)
iterator := csv.NewValueIterator(csv.ColumnKey, reader)
values := []client.Record{}
for {
value, err := iterator.NextRecord()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
values = append(values, value)
}
target := []pilosa.FieldValue{
{ColumnKey: "one", Value: 10},
{ColumnKey: "five", Value: -20},
{ColumnKey: "three", Value: 41},
}
if len(values) != len(target) {
t.Fatalf("There should be %d values, got %d", len(target), len(values))
}
for i := range target {
v := values[i].(client.FieldValue)
if !reflect.DeepEqual(pilosa.FieldValue(v), target[i]) {
t.Fatalf("%v != %v", target[i], values[i])
}
}
}
func TestCSValueIteratorWithInvalidFormat(t *testing.T) {
reader := strings.NewReader("1,2")
iterator := csv.NewValueIterator(csv.RowIDColumnID, reader)
_, err := iterator.NextRecord()
if err == nil {
t.Fatalf("should have failed")
}
}
func TestCSVColumnIteratorInvalidInput(t *testing.T) {
invalidInputs := []string{
// less than 2 columns
"155",
// invalid row ID
"a5,155",
// invalid column ID
"155,a5",
// invalid timestamp
"155,255,a5",
}
for _, text := range invalidInputs {
iterator := csv.NewColumnIterator(csv.RowIDColumnID, strings.NewReader(text))
_, err := iterator.NextRecord()
if err == nil {
t.Fatalf("CSVColumnIterator input: %s should fail", text)
}
}
}
func TestCSVValueIteratorInvalidInput(t *testing.T) {
invalidInputs := []string{
// less than 2 columns
"155",
// invalid column ID
"a5,155",
// invalid value
"155,a5",
}
for _, text := range invalidInputs {
iterator := csv.NewValueIterator(csv.ColumnID, strings.NewReader(text))
_, err := iterator.NextRecord()
if err == nil {
t.Fatalf("CSVValueIterator input: %s should fail", text)
}
}
}
func TestCSVColumnIteratorError(t *testing.T) {
iterator := csv.NewColumnIterator(csv.RowIDColumnID, &BrokenReader{})
_, err := iterator.NextRecord()
if err == nil {
t.Fatal("CSVColumnIterator should fail with error")
}
}
func TestCSVValueIteratorError(t *testing.T) {
iterator := csv.NewValueIterator(csv.ColumnID, &BrokenReader{})
_, err := iterator.NextRecord()
if err == nil {
t.Fatal("CSVValueIterator should fail with error")
}
}
type BrokenReader struct{}
func (r BrokenReader) Read(p []byte) (n int, err error) {
return 0, errors.New("broken reader")
}

55
client/doc.go Normal file
View file

@ -0,0 +1,55 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
/*
Package client enables querying a Pilosa server.
This client uses Pilosa's http+protobuf API.
Usage:
import (
"fmt"
"github.com/molecula/featurebase/v3/client"
)
// Create a Client instance
cli := client.DefaultClient()
// Create a Schema instance
schema, err := cli.Schema()
if err != nil {
panic(err)
}
// Create an Index instance
index, err := schema.Index("repository")
if err != nil {
panic(err)
}
// Create a Field instance
stargazer, err := index.Field("stargazer")
if err != nil {
panic(err)
}
// Sync the schema with the server-side, so non-existing indexes/fields are created on the server-side.
err = cli.SyncSchema(schema)
if err != nil {
panic(err)
}
// Execute a query
response, err := cli.Query(stargazer.Row(5))
if err != nil {
panic(err)
}
// Act on the result
fmt.Println(response.Result())
See also https://www.pilosa.com/docs/api-reference/ and https://www.pilosa.com/docs/query-language/.
*/
package client

View file

@ -0,0 +1,149 @@
# Data Model and Queries
## Indexes and Fields
*Index* and *field*s are the main data models of Pilosa. You can check the [Pilosa documentation](https://www.pilosa.com/docs/latest/data-model/) for more detail about the data model.
The `schema.Index` function is used to create an index instance. Note that this does not create an index on the server; the index object simply defines the schema.
```go
schema := client.NewSchema()
repository := schema.Index("repository")
```
You can pass options while creating index instances:
```go
repository := schema.Index("repository", pilosa.OptIndexKeys(true))
```
Field definitions are created with a call to the `Field` function of an index:
```go
stargazer := repository.Field("stargazer")
```
You can pass options to fields:
```go
stargazer := repository.Field("stargazer", pilosa.OptFieldTypeTime(TimeQuantumYearMonthDay))
```
In case the schema already exists on the server, you can retrieve that instead of creating the schema:
```go
cli := client.DefaultClient()
schema, err := cli.Schema()
if err != nil {
// act on the error
}
repository := schema.Index("repository")
```
## Queries
Once you have indexes and field definitions, you can create queries for them. Some of the queries work on the columns; corresponding methods are attached to the index. Other queries work on rows with related methods attached to fields.
For instance, `Row` queries work on rows; use a `Field` object to create those queries:
```go
rowQuery := stargazer.Row(1) // corresponds to PQL: Row(stargazer=1)
```
`Union` queries work on columns; use the index to create them:
```go
query := repository.Union(rowQuery1, rowQuery2)
```
In order to increase throughput, you may want to batch queries sent to the Pilosa server. The `index.BatchQuery` function is used for that purpose:
```go
query := repository.BatchQuery(
stargazer.Row(1),
repository.Union(stargazer.Row(100), stargazer.Row(5)))
```
The recommended way of creating query instances is using dedicated functions attached to index and field objects, but sometimes it would be desirable to send raw queries to Pilosa. You can use `index.RawQuery` method for that. Note that query string is not validated before sending to the server:
```go
query := repository.RawQuery("Row(stargazer=5)")
```
Raw queries are only sent to the coordinator node of a Pilosa cluster, so currently there's a possible performance hit using them instead of ORM functions attached to index or field instances.
This client supports [range queries using bit sliced indexes (BSI)](https://www.pilosa.com/docs/latest/query-language/#range-bsi). Read the [Range Encoded Bitmaps](https://www.pilosa.com/blog/range-encoded-bitmaps/) blog post for more information about the BSI implementation of range encoding in Pilosa.
In order to use BSI range queries, an integer field should be created. The field should have its minimum and maximum set. Here's how you would do that:
```go
index := schema.Index("animals")
captivity := index.Field("captivity", pilosa.OptFieldTypeInt(0, 956))
```
If the field with the necessary field already exists on the server, you don't need to create the field instance, `cli.SyncSchema(schema)` would load that to `schema`. You can then add some data:
```go
// Add the captivity values to the field.
data := []int{3, 392, 47, 956, 219, 14, 47, 504, 21, 0, 123, 318}
query := index.BatchQuery()
for i, x := range data {
column := uint64(i + 1)
query.Add(captivity.SetIntValue(column, x))
}
cli.Query(query)
```
Let's write a range query:
```go
// Query for all animals with more than 100 specimens
response, _ := cli.Query(captivity.GT(100))
fmt.Println(response.Result().Row().Columns)
// Query for the total number of animals in captivity
response, _ = cli.Query(captivity.Sum(nil))
fmt.Println(response.Result().Value())
```
If you pass a row query to `Sum` as a filter, then only the columns matching the filter will be considered in the `Sum` calculation:
```go
// Let's run a few set queries first
cli.Query(index.BatchQuery(
field.Set(42, 1),
field.Set(42, 6)))
// Query for the total number of animals in captivity where row 42 is set
response, _ = cli.Query(captivity.Sum(field.Row(42)))
fmt.Println(response.Result().Value())
```
See the functions further below for the list of functions that can be used with a `Field`.
Please check [Pilosa documentation](https://www.pilosa.com/docs) for PQL details. Here is a list of methods corresponding to PQL calls:
Index:
* `Union(rows *PQLRowQuery...) *PQLRowQuery`
* `Intersect(rows *PQLRowQuery...) *PQLRowQuery`
* `Difference(rows *PQLRowQuery...) *PQLRowQuery`
* `Xor(rows ...*PQLRowQuery) *PQLRowQuery`
* `Not(row) *PQLRowQuery`
* `Count(row *PQLRowQuery) *PQLBaseQuery`
* `Options(row *PQLRowQuery, opts ...OptionsOption) *PQLBaseQuery`
Field:
* `Row(rowID uint64) *PQLRowQuery`
* `Set(rowID uint64, columnID uint64) *PQLBaseQuery`
* `SetTimestamp(rowID uint64, columnID uint64, timestamp time.Time) *PQLBaseQuery`
* `Clear(rowID uint64, columnID uint64) *PQLBaseQuery`
* `TopN(n uint64) *PQLRowQuery`
* `RowTopN(n uint64, row *PQLRowQuery) *PQLRowQuery`
* `Range(rowID uint64, start time.Time, end time.Time) *PQLRowQuery`
* `RowRange(rowID uint64, start time.Time, end time.Time) *PQLRowQuery`
* `ClearRow(rowIDOrKey interface{}) *PQLBaseQuery`
* `Store(row *PQLRowQuery, rowIDOrKey interface{}) *PQLBaseQuery`
* `LT(n int) *PQLRowQuery`
* `LTE(n int) *PQLRowQuery`
* `GT(n int) *PQLRowQuery`
* `GTE(n int) *PQLRowQuery`
* `Between(a int, b int) *PQLRowQuery`
* `Sum(row *PQLRowQuery) *PQLBaseQuery`
* `Min(row *PQLRowQuery) *PQLBaseQuery`
* `Max(row *PQLRowQuery) *PQLBaseQuery`
* `SetIntValue(columnID uint64, value int) *PQLBaseQuery`

View file

@ -0,0 +1,160 @@
# Server Interaction
## Pilosa URI
A Pilosa URI has the `${SCHEME}://${HOST}:${PORT}` format:
* **Scheme**: Protocol of the URI. Default: `http`.
* **Host**: Hostname or ipv4/ipv6 IP address. Default: localhost.
* **Port**: Port number. Default: `10101`.
All parts of the URI are optional, but at least one of them must be specified. The following are equivalent:
* `http://localhost:10101`
* `http://localhost`
* `http://:10101`
* `localhost:10101`
* `localhost`
* `:10101`
A Pilosa URI is represented by the `github.com/pilosa/pilosa/v2/net URI` struct. Below are a few ways to create `URI` objects:
```go
import pnet "github.com/pilosa/pilosa/v2/net"
// create the default URI: http://localhost:10101
uri1 := pnet.DefaultURI()
// create a URI from string address
uri2, err := pnet.NewURIFromAddress("index1.pilosa.com:20202");
// create a URI with the given host and port
uri3, err := pnet.NewURIFromHostPort("index1.pilosa.com", 20202);
```
## Pilosa Client
In order to interact with a Pilosa server, an instance of `client.Client` should be created. The client is thread-safe and uses a pool of connections to the server, so we recommend creating a single instance of the client and sharing it when necessary.
If the Pilosa server is running at the default address (`http://localhost:10101`) you can create the client with default options using:
```go
import "github.com/pilosa/pilosa/v2/client"
cli := client.DefaultClient()
```
To use a custom server address, use the `NewClient` function:
```go
uri, err := pnet.NewURIFromAddress("http://index1.pilosa.com:15000")
if err != nil {
// Act on the error
}
cli, err := client.NewClient(uri)
```
Equivalently:
```go
cli, err := client.NewClient("http://index1.pilosa.com:15000")
```
If you are running a cluster of Pilosa servers, you can create a `Cluster` struct that keeps addresses of those servers:
```go
uri1, err := pnet.NewURIFromAddress(":10101")
uri2, err := pnet.NewURIFromAddress(":10110")
uri3, err := pnet.NewURIFromAddress(":10111")
cluster := client.NewClusterWithHost(uri1, uri2, uri3)
// Create a client with the cluster
cli, err := client.NewClient(cluster)
```
That is equivalent to:
```go
cli, err := client.NewClient([]string{":10101", ":10110", ":10111"})
```
It is possible to customize the behaviour of the underlying HTTP client by passing `ClientOption` structs to the `NewClient` function:
```go
cli, err := client.NewClient(cluster,
client.OptClientConnectTimeout(1000), // if can't connect in a second, close the connection
client.OptClientSocketTimeout(10000), // if no response received in 10 seconds, close the connection
client.OptClientPoolSizePerRoute(3), // number of connections in the pool per host
client.OptClientTotalPoolSize(10)) // number of total connections in the pool
```
Once you create a client, you can create indexes, fields or start sending queries.
Here is how you would create a index and field:
```go
// materialize repository index definition and stargazer field definition initialized before
err := cli.SyncSchema(schema)
```
You can send queries to a Pilosa server using the `Query` function of the `Client` struct:
```go
response, err := cli.Query(field.Row(5));
```
## Server Response
When a query is sent to a Pilosa server, the server either fulfills the query or sends an error message. In the case of an error, a `pilosa.Error` struct is returned, otherwise a `QueryResponse` struct is returned.
A `QueryResponse` struct may contain zero or more results of `QueryResult` type. You can access all results using the `Results` function of `QueryResponse` (which returns a list of `QueryResult` objects), or you can use the `Result` method (which returns either the first result or `nil` if there are no results):
```go
response, err := cli.Query(field.Row(5))
if err != nil {
// Act on the error
}
// check that there's a result and act on it
result := response.Result()
if result != nil {
// Act on the result
}
// iterate over all results
for _, result := range response.Results() {
// Act on the result
}
```
`QueryResult` objects contain:
* `Row()` function to retrieve a row result,
* `CountItems()` function to retrieve column count per row ID entries returned from `TopN` queries,
* `Count()` function to retrieve the number of rows per the given row ID returned from `Count` queries.
* `Value()` function to retrieve the result of `Min`, `Max` or `Sum` queries.
* `Changed()` function returns whether a `Set` or `Clear` query changed a column.
```go
row := result.Row()
columns := row.Columns
countItems := result.CountItems()
count := result.Count()
value := result.Value()
changed := result.Changed()
```
## SSL/TLS
Make sure the Pilosa server runs on a TLS address. [How To Set Up a Secure Cluster](https://www.pilosa.com/docs/latest/tutorials/#how-to-set-up-a-secure-cluster) tutorial explains how to do that.
In order to enable TLS support on the client side, the scheme of the address should be explicitly specified as `https`, e.g.: `https://01.pilosa.local:10501`
This client library uses the `net/http` module of Go standard library. You can pass a [tls.Config](https://golang.org/pkg/crypto/tls/#Config) struct in a `pilosa.TLSConfig` option to the client. If the Pilosa server is using a certificate from a recognized authority, you can use the defaults.
If you are using a self signed certificate, just pass `pilosa.TLSConfig(&tls.Config{InsecureSkipVerify: true})` to `pilosa.NewClient` function:
```go
client, _ := pilosa.NewClient("https://01.pilosa.local:10501", pilosa.TLSConfig(&tls.Config{InsecureSkipVerify: true}))
```

111
client/docs/tracing.md Normal file
View file

@ -0,0 +1,111 @@
# Tracing
Pilosa client supports distributed tracing via the [OpenTracing](https://opentracing.io/) API.
In order to use a tracer with Go-Pilosa, you should:
1. Create the tracer,
2. Pass the `OptClientOption(tracer)` to `NewClient`.
In this document, we will be using the [Jaeger](https://www.jaegertracing.io) tracer, but OpenTracing has support for [other tracing systems](https://opentracing.io/docs/supported-tracers/).
## Running the Pilosa Server
Let's run a temporary Pilosa container:
$ docker run -it --rm -p 10101:10101 pilosa/pilosa:v1.2.0
Check that you can access Pilosa:
$ curl localhost:10101
Welcome. Pilosa is running. Visit https://www.pilosa.com/docs/ for more information.
## Running the Jaeger Server
Let's run a Jaeger Server container:
$ docker run -it --rm -p 5775:5775/udp -p 16686:16686 jaegertracing/all-in-one:latest
...<title>Jaeger UI</title>...
## Writing the Sample Code
The sample code depdends on the Jaeger Go client, so let's install it first:
$ go get -u github.com/uber/jaeger-client-go/
Save the following sample code as `gopilosa-tracing.go`:
```go
package main
import (
"log"
"time"
"github.com/pilosa/pilosa/v2/client"
"github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/config"
)
func main() {
// Create the tracer.
cfg := config.Configuration{
Sampler: &config.SamplerConfig{
Type: "const",
Param: 1,
},
Reporter: &config.ReporterConfig{
LogSpans: true,
BufferFlushInterval: 1 * time.Second,
// Jaeger Server address
LocalAgentHostPort: "127.0.0.1:5775",
},
}
tracer, closer, err := cfg.New(
"go_pilosa_test",
config.Logger(jaeger.StdLogger),
)
// Don't forget to close the tracer.
defer closer.Close()
// Create the client, and pass the tracer.
cli, err := client.NewClient(":10101", pilosa.OptClientTracer(tracer))
if err != nil {
log.Fatal(err)
}
// Read the schema from the server.
// This should create a trace on the Jaeger server.
schema, err := cli.Schema()
if err != nil {
log.Fatal(err)
}
// Create and sync the sample schema.
// This should create a trace on the Jaeger server.
myIndex := schema.Index("my-index")
myField := myIndex.Field("my-field")
err = cli.SyncSchema(schema)
if err != nil {
log.Fatal(err)
}
// Run a query on Pilosa.
// This should create a trace on the Jaeger server.
_, err = cli.Query(myField.Set(1, 1000))
if err != nil {
log.Fatal(err)
}
}
```
## Checking the Tracing Data
Run the sample code:
$ go run gopilosa-tracing.go
* Open http://localhost:16686 in your web browser to visit Jaeger UI.
* Click on the *Search* tab and select `go_pilosa_test` in the *Service* dropdown on the right.
* Click on *Find Traces* button at the bottom left.
* You should see a couple of traces, such as: `Client.Query`, `Client.CreateField`, `Client.Schema`, etc.

110
client/egpool/egpool.go Normal file
View file

@ -0,0 +1,110 @@
// Copyright 2021 Molecula Corp. All rights reserved.
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 ErrPanic struct {
Value interface{}
}
func (p ErrPanic) 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(ErrPanic{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,37 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package egpool_test
import (
"errors"
"testing"
"github.com/molecula/featurebase/v3/client/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])
}
}
}

25
client/error.go Normal file
View file

@ -0,0 +1,25 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
import "github.com/pkg/errors"
// Predefined Pilosa errors.
var (
ErrEmptyCluster = errors.New("No usable addresses in the cluster")
ErrIndexExists = errors.New("Index exists")
ErrFieldExists = errors.New("Field exists")
ErrInvalidIndexName = errors.New("Invalid index name")
ErrInvalidFieldName = errors.New("Invalid field name")
ErrInvalidLabel = errors.New("Invalid label")
ErrInvalidKey = errors.New("Invalid key")
ErrTriedMaxHosts = errors.New("Tried max hosts, still failing")
ErrAddrURIClusterExpected = errors.New("Addresses, URIs or a cluster is expected")
ErrInvalidQueryOption = errors.New("Invalid query option")
ErrInvalidIndexOption = errors.New("Invalid index option")
ErrInvalidFieldOption = errors.New("Invalid field option")
ErrNoFragmentNodes = errors.New("No fragment nodes")
ErrNoShard = errors.New("Index has no shards")
ErrUnknownType = errors.New("Unknown type")
ErrSingleServerAddressRequired = errors.New("OptClientManualServerAddress requires a single URI or address")
ErrPreconditionFailed = errors.New("Precondition failed")
)

145
client/ingest_api_batch.go Normal file
View file

@ -0,0 +1,145 @@
package client
import (
"time"
"github.com/molecula/featurebase/v3/logger"
"github.com/pkg/errors"
)
// NewIngestAPIBatch creates an alternate implementation of
// RecordBatch which exists to aid in testing the new Ingest API and
// is likely far slower than the Batch.
func NewIngestAPIBatch(client *Client, size int, logger logger.Logger, fields []*Field) *ingestAPIBatch {
if len(fields) == 0 {
return nil
}
return &ingestAPIBatch{
client: client,
log: logger,
fields: fields,
keyed: fields[0].index.Opts().Keys(),
index: fields[0].index.Name(),
batchSize: size,
recordsK: make(map[string]map[string]interface{}),
records: make(map[uint64]map[string]interface{}),
}
}
type ingestAPIBatch struct {
client *Client
log logger.Logger
batchSize int
fields []*Field
keyed bool
index string
// map[recordKey][fieldName]value
recordsK map[string]map[string]interface{}
records map[uint64]map[string]interface{}
}
func (b *ingestAPIBatch) Add(row Row) error {
if len(row.Clears) > 0 {
return errors.New("ingest api batch does not support clears")
}
values := make(map[string]interface{})
for i, val := range row.Values {
field := b.fields[i]
// val can be string, uint64, int64, []string, []uint64, nil
// TODO timestamp field might need special handling
// TODO check that the Row.Clears field is only used for packed bools, and then issue a warning/error (in IDK) if the ingest API mode is used in conjunction w/ packed bools.
if val == nil {
continue
}
zero := QuantizedTime{}
if field.Options().Type() == FieldTypeTime && row.Time != zero {
timeq, err := row.Time.Time()
if err != nil {
return errors.Wrap(err, "parsing row time")
}
values[field.Name()] = map[string]interface{}{"time": timeq.Format(time.RFC3339), "values": val}
} else {
values[field.Name()] = val
}
}
if b.keyed {
switch rowID := row.ID.(type) {
case string:
b.recordsK[rowID] = values
case []byte:
b.recordsK[string(rowID)] = values
default:
return errors.Errorf("unsupported rowID %v of type %[1]T, must be string, or []byte for keyed index", rowID)
}
if len(b.recordsK) >= b.batchSize {
return ErrBatchNowFull
}
} else {
rowID, ok := row.ID.(uint64)
if !ok {
return errors.Errorf("unsupported rowID %v of type %[1]T, must be uint64 for unkeyed index", row.ID)
}
b.records[rowID] = values
if len(b.records) >= b.batchSize {
return ErrBatchNowFull
}
}
return nil
}
func (b *ingestAPIBatch) Import() error {
if b.keyed {
return b.importKeyed()
}
return b.importUnkeyed()
}
func (b *ingestAPIBatch) importKeyed() error {
req := []map[string]interface{}{
{
"action": "set",
"records": b.recordsK,
},
}
bod, err := b.client.IngestData(b.index, req)
if err != nil {
return errors.Wrapf(err, "importKeyed, body: %s", bod)
}
for k := range b.recordsK {
delete(b.recordsK, k)
}
return nil
}
func (b *ingestAPIBatch) importUnkeyed() error {
req := []map[string]interface{}{
{
"action": "set",
"records": b.records,
},
}
bod, err := b.client.IngestData(b.index, req)
if err != nil {
return errors.Wrapf(err, "importKeyed, body: %s", bod)
}
for v := range b.records {
delete(b.records, v)
}
return nil
}
func (b *ingestAPIBatch) Len() int {
if b.keyed {
return len(b.recordsK)
}
return len(b.records)
}
func (b *ingestAPIBatch) Flush() error { return nil }

View file

@ -0,0 +1,306 @@
package client
import (
"strings"
"testing"
"time"
"github.com/molecula/featurebase/v3/logger"
"github.com/molecula/featurebase/v3/test"
)
func TestIngestAPIBatchAdd(t *testing.T) {
t.Run("unkeyed", func(t *testing.T) {
batch := NewIngestAPIBatch(nil, 10, logger.NopLogger, []*Field{
{
name: "a",
index: &Index{name: "idxname", options: &IndexOptions{}},
options: &FieldOptions{
fieldType: FieldTypeSet,
},
},
{
name: "b",
index: &Index{name: "idxname", options: &IndexOptions{}},
options: &FieldOptions{
fieldType: FieldTypeSet,
keys: true,
},
},
{
name: "c",
index: &Index{name: "idxname", options: &IndexOptions{}},
options: &FieldOptions{
fieldType: FieldTypeTime,
keys: true,
},
},
})
qt := QuantizedTime{}
qt.Set(time.Date(2007, time.January, 1, 15, 0, 0, 0, time.UTC))
err := batch.Add(Row{
ID: uint64(1),
Values: []interface{}{uint64(2), "bkey", "ckey"},
Time: qt,
})
if err != nil {
t.Fatalf("adding row to batch: %v", err)
}
if batch.records[1]["a"] != uint64(2) {
t.Fatalf("unexpected batch.records: %+v", batch.records)
}
if batch.records[1]["b"] != "bkey" {
t.Fatalf("unexpected batch.records: %+v", batch.records)
}
if batch.records[1]["c"].(map[string]interface{})["time"] != "2007-01-01T15:00:00Z" {
t.Fatalf("unexpected batch.records: %+v", batch.records)
}
if batch.records[1]["c"].(map[string]interface{})["values"] != "ckey" {
t.Fatalf("unexpected batch.records: %+v", batch.records)
}
})
t.Run("keyed", func(t *testing.T) {
batch := NewIngestAPIBatch(nil, 10, logger.NopLogger, []*Field{
{
name: "a",
index: &Index{name: "idxname", options: &IndexOptions{keys: true}},
options: &FieldOptions{
fieldType: FieldTypeSet,
},
},
{
name: "b",
index: &Index{name: "idxname", options: &IndexOptions{keys: true}},
options: &FieldOptions{
fieldType: FieldTypeSet,
keys: true,
},
},
{
name: "c",
index: &Index{name: "idxname", options: &IndexOptions{keys: true}},
options: &FieldOptions{
fieldType: FieldTypeTime,
keys: true,
},
},
})
qt := QuantizedTime{}
qt.Set(time.Date(2007, time.January, 1, 15, 0, 0, 0, time.UTC))
err := batch.Add(Row{
ID: "1",
Values: []interface{}{uint64(2), "bkey", "ckey"},
Time: qt,
})
checkResult := func(batch *ingestAPIBatch, id string, err error) {
if err != nil {
t.Fatalf("adding row to batch: %v", err)
}
if batch.recordsK[id]["a"] != uint64(2) {
t.Fatalf("unexpected batch.records: %+v", batch.recordsK)
}
if batch.recordsK[id]["b"] != "bkey" {
t.Fatalf("unexpected batch.records: %+v", batch.recordsK)
}
if batch.recordsK[id]["c"].(map[string]interface{})["time"] != "2007-01-01T15:00:00Z" {
t.Fatalf("unexpected batch.records: %+v", batch.recordsK)
}
if batch.recordsK[id]["c"].(map[string]interface{})["values"] != "ckey" {
t.Fatalf("unexpected batch.records: %+v", batch.recordsK)
}
}
checkResult(batch, "1", err)
// test wrong type row ID
if err := batch.Add(Row{ID: 64.5}); !strings.Contains(err.Error(), "unsupported rowID") {
t.Fatalf("unexpected error w/ floating point rowID: %v", err)
}
// test that byte slice ID works same as string
err = batch.Add(Row{
ID: []byte("2"),
Values: []interface{}{uint64(2), "bkey", "ckey"},
Time: qt,
})
checkResult(batch, "2", err)
})
}
func TestIngestAPIBatch(t *testing.T) {
t.Skip("causing sporadic CI failures... on my list to debug, but this code doesn't affect anyone's production anyhow (jaffee)")
c := test.MustRunCluster(t, 3)
defer c.Close()
urls := make([]string, len(c.Nodes))
for i, n := range c.Nodes {
urls[i] = n.URL()
}
// Create a new client for the cluster
cli, err := newClientFromAddresses(urls, &ClientOptions{})
if err != nil {
t.Fatalf("getting new client: %v", err)
}
defer cli.Close()
cli.IngestSchema(map[string]interface{}{
"index-name": "test-1",
"index-action": "create",
"primary-key-type": "uint",
"field-action": "create",
"fields": []map[string]interface{}{
{
"field-name": "astr",
"field-type": "string",
"field-options": map[string]interface{}{},
},
{
"field-name": "bint",
"field-type": "int",
"field-options": map[string]interface{}{},
},
{
"field-name": "cid",
"field-type": "id",
"field-options": map[string]interface{}{},
},
{
"field-name": "dtimestamp",
"field-type": "timestamp",
"field-options": map[string]interface{}{
"unit": "s",
},
},
{
"field-name": "etime",
"field-type": "string",
"field-options": map[string]interface{}{
"time-quantum": "YMD",
},
},
{
"field-name": "fdecimal",
"field-type": "decimal",
"field-options": map[string]interface{}{
"scale": 3,
},
},
{
"field-name": "gbool",
"field-type": "bool",
"field-options": map[string]interface{}{},
},
},
})
schema, err := cli.Schema()
if err != nil {
t.Fatalf("getting schema: %v", err)
}
index := schema.Index("test-1")
defer cli.DeleteIndex(index)
batch := NewIngestAPIBatch(cli, 10, logger.NopLogger, []*Field{
{
name: "astr",
index: &Index{name: "test-1", options: &IndexOptions{}},
options: &FieldOptions{fieldType: FieldTypeSet, keys: true},
},
{
name: "bint",
options: &FieldOptions{fieldType: FieldTypeInt},
},
{
name: "cid",
options: &FieldOptions{fieldType: FieldTypeSet, keys: false},
},
{
name: "dtimestamp",
options: &FieldOptions{fieldType: FieldTypeTimestamp},
},
{
name: "etime",
options: &FieldOptions{fieldType: FieldTypeTime, keys: true, timeQuantum: TimeQuantumYearMonthDay},
},
{
name: "fdecimal",
options: &FieldOptions{fieldType: FieldTypeDecimal, scale: 3},
},
{
name: "gbool",
options: &FieldOptions{fieldType: FieldTypeBool},
},
})
qt0 := &QuantizedTime{}
qt0.Set(time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC))
if err := batch.Add(Row{
ID: uint64(7),
Values: []interface{}{"a", -2, 9, 1287367623, "e", 1.2345, true},
Time: *qt0,
}); err != nil {
t.Fatalf("adding row: %v", err)
}
// test nil value case
if err := batch.Add(Row{
ID: uint64(8),
Values: []interface{}{nil, nil, nil, nil, nil, nil, nil},
Time: QuantizedTime{},
}); err != nil {
t.Fatalf("error adding all nil batch which should affect nothing: %v", err)
}
if err := batch.Import(); err != nil {
t.Fatalf("importing row: %v", err)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(astr=a)", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(asr=a) result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(bint==-2)", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(bint==-2) result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(cid=9)", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(cid=9) result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(dtimestamp=='2010-10-18T02:07:03Z')", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(dtimestamp=='2010-10-18T02:07:03Z') result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(etime=e, from='2010-01-01', to='2010-01-02')", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(etime=e, from='2010-01-01', to='2010-01-02') result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(fdecimal==1.234)", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(fdecimal==1.234) result: %+v", resp.Result().Row().Columns)
}
if resp, err := cli.Query(NewPQLBaseQuery("Row(gbool=true)", &Index{name: "test-1", options: &IndexOptions{}}, nil)); err != nil {
t.Fatalf("querying: %v", err)
} else if len(resp.Result().Row().Columns) != 1 || resp.Result().Row().Columns[0] != uint64(7) {
t.Fatalf("unexpected Row(gbool=true) result: %+v", resp.Result().Row().Columns)
}
}

32
client/logimport.go Normal file
View file

@ -0,0 +1,32 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
import (
"encoding/gob"
"io"
)
type importLog struct {
Index string
Path string
Shard uint64
IsRoaring bool
Timestamp int64 // Unix Nanoseconds
Data []byte
}
type encoder interface {
Encode(thing interface{}) error
}
func newImportLogEncoder(w io.Writer) encoder {
return gob.NewEncoder(w)
}
type decoder interface {
Decode(thing interface{}) error
}
func newImportLogDecoder(r io.Reader) decoder {
return gob.NewDecoder(r)
}

142
client/logimport_test.go Normal file
View file

@ -0,0 +1,142 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"reflect"
"testing"
)
func TestEncodeDecode(t *testing.T) {
tests := []importLog{
{
Index: "go-testindex",
Path: "/index/go-testindex/field/importfield-batchsize/import?clear=false",
Shard: 0,
Data: make([]byte, 3918),
},
{
Index: "go-testindex",
Path: "/index/go-testindex/field/importfield-batchsize/import?clear=false",
Shard: 0,
Data: make([]byte, 3918),
},
{
Index: "eheh",
Path: "blah",
Shard: 9,
Data: []byte("something"),
},
{
Index: "",
Path: "",
Shard: 0,
Data: nil,
},
{
Index: "eheh",
Path: "blah",
Shard: 10,
Data: []byte("blahaslkdjfeoiwujf"),
},
{
Index: "eheh",
Path: "blah",
Shard: 10,
Data: make([]byte, 10000),
},
{
Index: "zoop",
Path: "blah",
Shard: 8923734,
Data: []byte("blahaslkdjfeoiwujf"),
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
nl := importLog{
Index: test.Index,
Path: test.Path,
Shard: test.Shard,
Data: make([]byte, len(test.Data)),
}
copy(nl.Data, test.Data)
buf := &bytes.Buffer{}
enc := newImportLogEncoder(buf)
err := enc.Encode(nl)
if err != nil {
t.Fatalf("writing to buf: %v", err)
}
dec := newImportLogDecoder(buf)
l2 := &importLog{}
err = dec.Decode(l2)
if err != nil {
t.Fatalf("reading from buf: %v", err)
}
if l2.Index != test.Index {
t.Errorf("indexes not equal:\n%s\n%s", test.Index, l2.Index)
}
if l2.Path != test.Path {
t.Errorf("paths not equal:\n%s\n%s", test.Path, l2.Path)
}
if l2.Shard != test.Shard {
t.Errorf("shards not equal exp: %d got %d", test.Shard, l2.Shard)
}
if !reflect.DeepEqual(test.Data, l2.Data) {
t.Errorf("data not equal \n%v\n%v", test.Data, l2.Data)
}
})
}
buf, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("getting temp file: %v", err)
}
enc := newImportLogEncoder(buf)
for _, test := range tests {
a := &test
err := enc.Encode(a)
if err != nil {
t.Errorf("encoding to buf: %v", err)
}
}
name := buf.Name()
err = buf.Close()
if err != nil {
t.Fatalf("closing temp file: %v", err)
}
buf, err = os.Open(name)
if err != nil {
t.Fatalf("reopening: %v", err)
}
dec := newImportLogDecoder(buf)
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
l := &importLog{}
err := dec.Decode(l)
// err := l.ReadFrom(buf)
if err != nil {
t.Errorf("reading from buf: %v", err)
}
if l.Index != test.Index {
t.Errorf("indexes not equal:\n%s\n%s", test.Index, l.Index)
}
if l.Path != test.Path {
t.Errorf("paths not equal:\n%s\n%s", test.Path, l.Path)
}
if l.Shard != test.Shard {
t.Errorf("shards not equal exp: %d got %d", test.Shard, l.Shard)
}
if !reflect.DeepEqual(test.Data, l.Data) {
t.Errorf("data not equal \n%v\n%v", test.Data, l.Data)
}
})
}
}

16
client/metrics.go Normal file
View file

@ -0,0 +1,16 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package client
const (
// MetricBatchImportDurationSeconds records the full time of the
// RecordBatch.Import call. This includes starting and finishing a
// transaction, doing key translation, building fragments locally,
// importing all data, and resetting internal structures.
MetricBatchImportDurationSeconds = "batch_import_duration_seconds"
// MetricBatchFlushDurationSeconds records the full time for
// RecordBatch.Flush (if splitBatchMode is in use). This includes
// starting and finishing a transaction, importing all data, and
// resetting internal structures.
MetricBatchFlushDurationSeconds = "batch_flush_duration_seconds"
)

1569
client/orm.go Normal file

File diff suppressed because it is too large Load diff

1197
client/orm_test.go Normal file

File diff suppressed because it is too large Load diff

62
client/record.go Normal file
View file

@ -0,0 +1,62 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
// Record is a Column or a FieldValue.
type Record interface {
Shard(shardWidth uint64) uint64
Less(other Record) bool
}
// RecordIterator is an iterator for a record.
type RecordIterator interface {
NextRecord() (Record, error)
}
// Column defines a single Pilosa column.
type Column struct {
RowID uint64
ColumnID uint64
RowKey string
ColumnKey string
Timestamp int64
}
// Shard returns the shard for this column.
func (b Column) Shard(shardWidth uint64) uint64 {
return b.ColumnID / shardWidth
}
// Less returns true if this column sorts before the given Record.
func (b Column) Less(other Record) bool {
if ob, ok := other.(Column); ok {
if b.RowID == ob.RowID {
return b.ColumnID < ob.ColumnID
}
return b.RowID < ob.RowID
}
return false
}
// FieldValue represents the value for a column within a
// range-encoded field.
type FieldValue struct {
ColumnID uint64
ColumnKey string
Value int64
}
// Shard returns the shard for this field value.
func (v FieldValue) Shard(shardWidth uint64) uint64 {
return v.ColumnID / shardWidth
}
// Less returns true if this field value sorts before the given Record.
func (v FieldValue) Less(other Record) bool {
if ov, ok := other.(FieldValue); ok {
return v.ColumnID < ov.ColumnID
}
return false
}

70
client/record_test.go Normal file
View file

@ -0,0 +1,70 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client_test
import (
"testing"
"github.com/molecula/featurebase/v3/client"
)
func TestColumnShard(t *testing.T) {
a := client.Column{RowID: 15, ColumnID: 55, Timestamp: 100101}
target := uint64(0)
if a.Shard(100) != target {
t.Fatalf("shard %d != %d", target, a.Shard(100))
}
target = 5
if a.Shard(10) != target {
t.Fatalf("shard %d != %d", target, a.Shard(10))
}
}
func TestColumnLess(t *testing.T) {
a := client.Column{RowID: 10, ColumnID: 200}
a2 := client.Column{RowID: 10, ColumnID: 1000}
b := client.Column{RowID: 200, ColumnID: 10}
c := client.FieldValue{ColumnID: 1}
if !a.Less(a2) {
t.Fatalf("%v should be less than %v", a, a2)
}
if !a.Less(b) {
t.Fatalf("%v should be less than %v", a, b)
}
if b.Less(a) {
t.Fatalf("%v should not be less than %v", b, a)
}
if c.Less(a) {
t.Fatalf("%v should not be less than %v", c, a)
}
}
func TestFieldValueShard(t *testing.T) {
a := client.FieldValue{ColumnID: 55, Value: 125}
target := uint64(0)
if a.Shard(100) != target {
t.Fatalf("shard %d != %d", target, a.Shard(100))
}
target = 5
if a.Shard(10) != target {
t.Fatalf("shard %d != %d", target, a.Shard(10))
}
}
func TestFieldValueLess(t *testing.T) {
a := client.FieldValue{ColumnID: 55, Value: 125}
b := client.FieldValue{ColumnID: 100, Value: 125}
c := client.Column{ColumnID: 1, RowID: 2}
if !a.Less(b) {
t.Fatalf("%v should be less than %v", a, b)
}
if b.Less(a) {
t.Fatalf("%v should not be less than %v", b, a)
}
if c.Less(a) {
t.Fatalf("%v should not be less than %v", c, a)
}
}

495
client/response.go Normal file
View file

@ -0,0 +1,495 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"encoding/json"
"fmt"
"github.com/molecula/featurebase/v3/pb"
)
// QueryResponse types.
const (
QueryResultTypeNil uint32 = iota
QueryResultTypeRow
QueryResultTypePairs
QueryResultTypePairsField
QueryResultTypeValCount
QueryResultTypeUint64
QueryResultTypeBool
QueryResultTypeRowIDs // this is not used by the client
QueryResultTypeGroupCounts
QueryResultTypeRowIdentifiers
QueryResultTypePair
QueryResultTypePairField
QueryResultTypeSignedRow
)
// QueryResponse represents the response from a Pilosa query.
type QueryResponse struct {
ResultList []QueryResult `json:"results,omitempty"`
ErrorMessage string `json:"error-message,omitempty"`
Success bool `json:"success,omitempty"`
}
func newQueryResponseFromInternal(response *pb.QueryResponse) (*QueryResponse, error) {
if response.Err != "" {
return &QueryResponse{
ErrorMessage: response.Err,
Success: false,
}, nil
}
results := make([]QueryResult, 0, len(response.Results))
for _, r := range response.Results {
result, err := newQueryResultFromInternal(r)
if err != nil {
return nil, err
}
results = append(results, result)
}
return &QueryResponse{
ResultList: results,
Success: true,
}, nil
}
// Results returns all results in the response.
func (qr *QueryResponse) Results() []QueryResult {
return qr.ResultList
}
// Result returns the first result or nil.
func (qr *QueryResponse) Result() QueryResult {
if len(qr.ResultList) == 0 {
return nil
}
return qr.ResultList[0]
}
// QueryResult represents one of the results in the response.
type QueryResult interface {
Type() uint32
Row() RowResult
CountItems() []CountResultItem
CountItem() CountResultItem
Count() int64
Value() int64
Changed() bool
GroupCounts() []GroupCount
RowIdentifiers() RowIdentifiersResult
}
func newQueryResultFromInternal(result *pb.QueryResult) (QueryResult, error) {
switch result.Type {
case QueryResultTypeNil:
return NilResult{}, nil
case QueryResultTypeRow:
return newRowResultFromInternal(result.Row)
case QueryResultTypePairs:
return countItemsFromInternal(result.Pairs), nil
case QueryResultTypePairsField:
return countItemsFromInternal(result.PairsField.Pairs), nil
case QueryResultTypeValCount:
return &ValCountResult{
Val: result.ValCount.Val,
Cnt: result.ValCount.Count,
}, nil
case QueryResultTypeUint64:
return IntResult(result.N), nil
case QueryResultTypeBool:
return BoolResult(result.Changed), nil
case QueryResultTypeRowIdentifiers:
return &RowIdentifiersResult{
IDs: result.RowIdentifiers.Rows,
Keys: result.RowIdentifiers.Keys,
}, nil
case QueryResultTypeGroupCounts:
return groupCountsFromInternal(result.GroupCounts), nil
case QueryResultTypePair:
return CountItem{CountResultItem: countItemFromInternal(result.Pairs[0])}, nil
case QueryResultTypePairField:
return CountItem{CountResultItem: countItemFromInternal(result.PairField.Pair)}, nil
}
return nil, ErrUnknownType
}
// CountResultItem represents a result from TopN call.
type CountResultItem struct {
ID uint64 `json:"id"`
Key string `json:"key,omitempty"`
Count uint64 `json:"count"`
}
func (c *CountResultItem) String() string {
if c.Key != "" {
return fmt.Sprintf("%s:%d", c.Key, c.Count)
}
return fmt.Sprintf("%d:%d", c.ID, c.Count)
}
type CountItem struct {
CountResultItem
}
// Type is the type of this result.
func (CountItem) Type() uint32 { return QueryResultTypePairField }
// Row returns a RowResult.
func (CountItem) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (t CountItem) CountItems() []CountResultItem { return []CountResultItem{t.CountResultItem} }
// CountItem returns a CountResultItem
func (t CountItem) CountItem() CountResultItem { return t.CountResultItem }
// Count returns the result of a Count call.
func (CountItem) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (CountItem) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (CountItem) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (CountItem) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (CountItem) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
func countItemFromInternal(item *pb.Pair) CountResultItem {
return CountResultItem{ID: item.ID, Key: item.Key, Count: item.Count}
}
func countItemsFromInternal(items []*pb.Pair) TopNResult {
result := make([]CountResultItem, 0, len(items))
for _, v := range items {
result = append(result, countItemFromInternal(v))
}
return TopNResult(result)
}
// TopNResult is returned from TopN call.
type TopNResult []CountResultItem
// Type is the type of this result.
func (TopNResult) Type() uint32 { return QueryResultTypePairsField }
// Row returns a RowResult.
func (TopNResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (t TopNResult) CountItems() []CountResultItem { return t }
// CountItem returns a CountResultItem
func (t TopNResult) CountItem() CountResultItem {
if len(t) >= 1 {
return t[0]
}
return CountResultItem{}
}
// Count returns the result of a Count call.
func (TopNResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (TopNResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (TopNResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (TopNResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (TopNResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// RowResult represents a result from Row, Union, Intersect, Difference and Range PQL calls.
type RowResult struct {
Columns []uint64 `json:"columns"`
Keys []string `json:"keys"`
}
func newRowResultFromInternal(row *pb.Row) (*RowResult, error) {
return &RowResult{
Columns: row.Columns,
Keys: row.Keys,
}, nil
}
// Type is the type of this result.
func (RowResult) Type() uint32 { return QueryResultTypeRow }
// Row returns a RowResult.
func (b RowResult) Row() RowResult { return b }
// CountItems returns a CountResultItem slice.
func (RowResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (RowResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (RowResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (RowResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (RowResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (RowResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (RowResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// MarshalJSON serializes this row result.
func (b RowResult) MarshalJSON() ([]byte, error) {
columns := b.Columns
if columns == nil {
columns = []uint64{}
}
keys := b.Keys
if keys == nil {
keys = []string{}
}
return json.Marshal(struct {
Columns []uint64 `json:"columns"`
Keys []string `json:"keys"`
}{
Columns: columns,
Keys: keys,
})
}
// ValCountResult is returned from Min, Max and Sum calls.
type ValCountResult struct {
Val int64 `json:"val"`
Cnt int64 `json:"count"`
}
// Type is the type of this result.
func (ValCountResult) Type() uint32 { return QueryResultTypeValCount }
// Row returns a RowResult.
func (ValCountResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (ValCountResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (ValCountResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (c ValCountResult) Count() int64 { return c.Cnt }
// Value returns the result of a Min, Max or Sum call.
func (c ValCountResult) Value() int64 { return c.Val }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (ValCountResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (ValCountResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (ValCountResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// IntResult is returned from Count call.
type IntResult int64
// Type is the type of this result.
func (IntResult) Type() uint32 { return QueryResultTypeUint64 }
// Row returns a RowResult.
func (IntResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (IntResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (IntResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (i IntResult) Count() int64 { return int64(i) }
// Value returns the result of a Min, Max or Sum call.
func (IntResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (IntResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (IntResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (IntResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// BoolResult is returned from Set and Clear calls.
type BoolResult bool
// Type is the type of this result.
func (BoolResult) Type() uint32 { return QueryResultTypeBool }
// Row returns a RowResult.
func (BoolResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (BoolResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (BoolResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (BoolResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (BoolResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (b BoolResult) Changed() bool { return bool(b) }
// GroupCounts returns the result of a GroupBy call.
func (BoolResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (BoolResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// NilResult is returned from calls which don't return a value.
type NilResult struct{}
// Type is the type of this result.
func (NilResult) Type() uint32 { return QueryResultTypeNil }
// Row returns a RowResult.
func (NilResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (NilResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (NilResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (NilResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (NilResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (NilResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (NilResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (NilResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// FieldRow represents a Group in a GroupBy call result.
type FieldRow struct {
FieldName string `json:"field"`
RowID uint64 `json:"rowID"`
RowKey string `json:"rowKey"`
Value *int64 `json:"value,omitempty"`
}
// GroupCount contains groups and their count in a GroupBy call result.
type GroupCount struct {
Groups []FieldRow `json:"groups"`
Count int64 `json:"count"`
Agg int64 `json:"agg"`
}
// GroupCountResult is returned from GroupBy call.
type GroupCountResult []GroupCount
// Type is the type of this result.
func (GroupCountResult) Type() uint32 { return QueryResultTypeGroupCounts }
// Row returns a RowResult.
func (GroupCountResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (GroupCountResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (GroupCountResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (GroupCountResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (GroupCountResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (GroupCountResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (r GroupCountResult) GroupCounts() []GroupCount { return r }
// RowIdentifiers returns the result of a Rows call.
func (GroupCountResult) RowIdentifiers() RowIdentifiersResult { return RowIdentifiersResult{} }
// RowIdentifiersResult is returned from a Rows call.
type RowIdentifiersResult struct {
IDs []uint64 `json:"ids"`
Keys []string `json:"keys,omitempty"`
}
// Type is the type of this result.
func (RowIdentifiersResult) Type() uint32 { return QueryResultTypeRowIdentifiers }
// Row returns a RowResult.
func (RowIdentifiersResult) Row() RowResult { return RowResult{} }
// CountItems returns a CountResultItem slice.
func (RowIdentifiersResult) CountItems() []CountResultItem { return nil }
// CountItem returns a CountResultItem
func (RowIdentifiersResult) CountItem() CountResultItem { return CountResultItem{} }
// Count returns the result of a Count call.
func (RowIdentifiersResult) Count() int64 { return 0 }
// Value returns the result of a Min, Max or Sum call.
func (RowIdentifiersResult) Value() int64 { return 0 }
// Changed returns whether the corresponding Set or Clear call changed the value of a bit.
func (RowIdentifiersResult) Changed() bool { return false }
// GroupCounts returns the result of a GroupBy call.
func (RowIdentifiersResult) GroupCounts() []GroupCount { return nil }
// RowIdentifiers returns the result of a Rows call.
func (r RowIdentifiersResult) RowIdentifiers() RowIdentifiersResult { return r }
func groupCountsFromInternal(items *pb.GroupCounts) GroupCountResult {
result := make([]GroupCount, 0, len(items.Groups))
for _, g := range items.Groups {
groups := make([]FieldRow, 0, len(g.Group))
for _, f := range g.Group {
fr := FieldRow{
FieldName: f.Field,
RowID: f.RowID,
RowKey: f.RowKey,
}
if f.Value != nil {
fr.Value = &f.Value.Value
}
groups = append(groups, fr)
}
result = append(result, GroupCount{
Groups: groups,
Count: int64(g.Count),
Agg: int64(g.Agg),
})
}
return GroupCountResult(result)
}

272
client/response_test.go Normal file
View file

@ -0,0 +1,272 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"encoding/json"
"fmt"
"log"
"reflect"
"testing"
"github.com/molecula/featurebase/v3/pb"
)
func TestNewRowResultFromInternal(t *testing.T) {
targetColumns := []uint64{5, 10}
row := &pb.Row{
Columns: []uint64{5, 10},
}
result, err := newRowResultFromInternal(row)
if err != nil {
t.Fatalf("Failed with error: %s", err)
}
if !reflect.DeepEqual(targetColumns, result.Columns) {
t.Fatal()
}
}
func TestNewQueryResponseFromInternal(t *testing.T) {
targetColumns := []uint64{5, 10}
targetCountItems := []CountResultItem{
{ID: 10, Count: 100},
}
row := &pb.Row{
Columns: []uint64{5, 10},
}
pairs := []*pb.Pair{
{ID: 10, Count: 100},
}
response := &pb.QueryResponse{
Results: []*pb.QueryResult{
{Type: QueryResultTypeRow, Row: row},
{Type: QueryResultTypePairs, Pairs: pairs},
},
Err: "",
}
qr, err := newQueryResponseFromInternal(response)
if err != nil {
t.Fatalf("Failed with error: %s", err)
}
if qr.ErrorMessage != "" {
t.Fatalf("ErrorMessage should be empty")
}
if !qr.Success {
t.Fatalf("IsSuccess should be true")
}
results := qr.Results()
if len(results) != 2 {
t.Fatalf("Number of results should be 2")
}
if results[0] != qr.Result() {
t.Fatalf("Result() should return the first result")
}
if !reflect.DeepEqual(targetColumns, results[0].Row().Columns) {
t.Fatalf("The row result should contain the columns")
}
if !reflect.DeepEqual(targetCountItems, results[1].CountItems()) {
t.Fatalf("The response should include count items")
}
}
func TestNewQueryResponseWithErrorFromInternal(t *testing.T) {
response := &pb.QueryResponse{
Err: "some error",
}
qr, err := newQueryResponseFromInternal(response)
if err != nil {
t.Fatalf("Failed with error: %s", err)
}
if qr.ErrorMessage != "some error" {
t.Fatalf("The response should include the error message")
}
if qr.Success {
t.Fatalf("IsSuccess should be false")
}
if qr.Result() != nil {
t.Fatalf("If there are no results, Result should return nil")
}
}
func TestCountResultItemToString(t *testing.T) {
tests := []struct {
item *CountResultItem
expected string
}{
{item: &CountResultItem{ID: 100, Count: 50}, expected: "100:50"},
{item: &CountResultItem{Key: "blah", Count: 50}, expected: "blah:50"},
{item: &CountResultItem{Key: "blah", ID: 22, Count: 50}, expected: "blah:50"},
{item: &CountResultItem{Key: "blah", ID: 22}, expected: "blah:0"},
{item: &CountResultItem{}, expected: "0:0"},
}
for i, tst := range tests {
t.Run(fmt.Sprintf("%d: ", i), func(t *testing.T) {
if tst.expected != tst.item.String() {
t.Fatalf("%s != %s", tst.expected, tst.item.String())
}
})
}
}
func TestMarshalResults(t *testing.T) {
row := &pb.Row{
Columns: []uint64{5, 10},
}
pairs := []*pb.Pair{
{ID: 10, Count: 100},
}
pbufResults := []*pb.QueryResult{
{Type: QueryResultTypeRow, Row: row},
{Type: QueryResultTypePairs, Pairs: pairs},
}
resultJSONStrings := make([]string, len(pbufResults))
for i, pr := range pbufResults {
r, err := newQueryResultFromInternal(pr)
if err != nil {
t.Fatal(err)
}
b, err := json.Marshal(r)
if err != nil {
t.Fatal(err)
}
resultJSONStrings[i] = string(b)
}
targetJSON := []string{
`{"columns":[5,10],"keys":[]}`,
`[{"id":10,"count":100}]`,
}
for i := range targetJSON {
if sortedString(targetJSON[i]) != sortedString(resultJSONStrings[i]) {
t.Fatalf("%v != %v ", targetJSON[i], resultJSONStrings[i])
}
}
}
func TestUnknownQueryResultType(t *testing.T) {
result := &pb.QueryResult{
Type: 999,
}
_, err := newQueryResultFromInternal(result)
if err != ErrUnknownType {
t.Fatalf("Should have failed with ErrUnknownType")
}
}
func TestTopNResult(t *testing.T) {
result := TopNResult{
CountResultItem{ID: 100, Count: 10},
}
expectResult(t, result, QueryResultTypePairsField, RowResult{}, []CountResultItem{{100, "", 10}}, 0, 0, false, nil, RowIdentifiersResult{})
}
func TestRowResult(t *testing.T) {
result := RowResult{
Columns: []uint64{1, 2, 3},
}
targetBmp := RowResult{
Columns: []uint64{1, 2, 3},
}
expectResult(t, result, QueryResultTypeRow, targetBmp, nil, 0, 0, false, nil, RowIdentifiersResult{})
}
func TestRowResultNilColumns(t *testing.T) {
result := RowResult{
Columns: nil,
}
_, err := result.MarshalJSON()
if err != nil {
t.Fatal(err)
}
}
func TestSumCountResult(t *testing.T) {
result := ValCountResult{
Val: 100,
Cnt: 50,
}
expectResult(t, result, QueryResultTypeValCount, RowResult{}, nil, 100, 50, false, nil, RowIdentifiersResult{})
}
func TestIntResult(t *testing.T) {
result := IntResult(11)
expectResult(t, result, QueryResultTypeUint64, RowResult{}, nil, 0, 11, false, nil, RowIdentifiersResult{})
}
func TestBoolResult(t *testing.T) {
result := BoolResult(true)
expectResult(t, result, QueryResultTypeBool, RowResult{}, nil, 0, 0, true, nil, RowIdentifiersResult{})
}
func TestNilResult(t *testing.T) {
result := NilResult{}
expectResult(t, result, QueryResultTypeNil, RowResult{}, nil, 0, 0, false, nil, RowIdentifiersResult{})
}
func TestGroupCountResult(t *testing.T) {
result := GroupCountResult{
{Groups: []FieldRow{{FieldName: "f1", RowID: 1}}, Count: 2},
{Groups: []FieldRow{{FieldName: "f1", RowID: 2}}, Count: 1},
}
expectResult(t, result, QueryResultTypeGroupCounts, RowResult{}, nil, 0, 0, false, []GroupCount{
{Groups: []FieldRow{{FieldName: "f1", RowID: 1}}, Count: 2},
{Groups: []FieldRow{{FieldName: "f1", RowID: 2}}, Count: 1},
}, RowIdentifiersResult{})
}
func TestGroupCountWithValueResult(t *testing.T) {
var a, b int64 = -1, 1
result := GroupCountResult{
{Groups: []FieldRow{{FieldName: "f1", Value: &a}}, Count: 1},
{Groups: []FieldRow{{FieldName: "f1", Value: &b}}, Count: 1},
}
var aa, bb int64 = -1, 1
expectResult(t, result, QueryResultTypeGroupCounts, RowResult{}, nil, 0, 0, false, []GroupCount{
{Groups: []FieldRow{{FieldName: "f1", Value: &aa}}, Count: 1},
{Groups: []FieldRow{{FieldName: "f1", Value: &bb}}, Count: 1},
}, RowIdentifiersResult{})
}
func TestRowIdentifiersResult(t *testing.T) {
result := RowIdentifiersResult{
IDs: []uint64{1, 2, 3, 4},
}
expectResult(t, result, QueryResultTypeRowIdentifiers, RowResult{}, nil, 0, 0, false, nil, RowIdentifiersResult{
IDs: []uint64{1, 2, 3, 4},
})
}
func expectResult(t *testing.T, r QueryResult, resultType uint32, bmp RowResult,
countItems []CountResultItem, sum int64, count int64, changed bool,
groupCounts []GroupCount, rowIdentifiers RowIdentifiersResult) {
if resultType != r.Type() {
log.Fatalf("Result type: %d != %d", resultType, r.Type())
}
if !reflect.DeepEqual(bmp, r.Row()) {
log.Fatalf("Row: %v != %v", bmp, r.Row())
}
if !reflect.DeepEqual(countItems, r.CountItems()) {
log.Fatalf("Count items: %v != %v", countItems, r.CountItems())
}
if count != r.Count() {
log.Fatalf("Count: %d != %d", count, r.Count())
}
if sum != r.Value() {
log.Fatalf("Sum: %d != %d", sum, r.Value())
}
if changed != r.Changed() {
log.Fatalf("Changed: %v != %v", changed, r.Changed())
}
if !reflect.DeepEqual(groupCounts, r.GroupCounts()) {
log.Fatalf("Group counts: %v != %v", groupCounts, r.GroupCounts())
}
if !reflect.DeepEqual(rowIdentifiers, r.RowIdentifiers()) {
log.Fatalf("Row identifiers: %v != %v", rowIdentifiers, r.RowIdentifiers())
}
}

53
client/shardnodes.go Normal file
View file

@ -0,0 +1,53 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"sync"
pnet "github.com/molecula/featurebase/v3/net"
)
type shardNodes struct {
data map[string]map[uint64][]*pnet.URI
mu *sync.RWMutex
}
func newShardNodes() shardNodes {
return shardNodes{
data: make(map[string]map[uint64][]*pnet.URI),
mu: &sync.RWMutex{},
}
}
func (s shardNodes) Get(index string, shard uint64) ([]*pnet.URI, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
if idx, ok := s.data[index]; ok {
if uris, ok := idx[shard]; ok {
return uris, true
}
}
return nil, false
}
func (s shardNodes) Put(index string, shard uint64, uris []*pnet.URI) {
s.mu.Lock()
defer s.mu.Unlock()
idx, ok := s.data[index]
if !ok {
idx = make(map[uint64][]*pnet.URI)
}
idx[shard] = uris
s.data[index] = idx
}
func (s shardNodes) Invalidate() {
s.mu.Lock()
defer s.mu.Unlock()
for k := range s.data {
delete(s.data, k)
}
}

76
client/tracer.go Normal file
View file

@ -0,0 +1,76 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
opentracing "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/log"
)
type NoopTracer struct{}
type NoopSpan struct{}
func (s NoopSpan) Finish() {
// pass
}
func (s NoopSpan) FinishWithOptions(opts opentracing.FinishOptions) {
// pass
}
func (s NoopSpan) Context() opentracing.SpanContext {
return nil
}
func (s NoopSpan) SetOperationName(operationName string) opentracing.Span {
return s
}
func (s NoopSpan) SetTag(key string, value interface{}) opentracing.Span {
return s
}
func (s NoopSpan) LogFields(fields ...log.Field) {
// pass
}
func (s NoopSpan) LogKV(alternatingKeyValues ...interface{}) {
// pass
}
func (s NoopSpan) SetBaggageItem(restrictedKey, value string) opentracing.Span {
return s
}
func (s NoopSpan) BaggageItem(restrictedKey string) string {
return ""
}
func (s NoopSpan) Tracer() opentracing.Tracer {
return nil
}
func (s NoopSpan) LogEvent(event string) {
// pass
}
func (s NoopSpan) LogEventWithPayload(event string, payload interface{}) {
// pass
}
func (s NoopSpan) Log(data opentracing.LogData) {
// pass
}
func (t NoopTracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span {
return NoopSpan{}
}
func (t NoopTracer) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error {
return nil
}
func (t NoopTracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
return nil, nil
}

41
client/validate.go Normal file
View file

@ -0,0 +1,41 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import (
"regexp"
)
const (
maxLabel = 64
maxKey = 64
)
var labelRegex = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_-]*$")
var keyRegex = regexp.MustCompile("^[A-Za-z0-9_{}+/=.~%:-]*$")
// ValidLabel returns true if the given label is valid, otherwise false.
func ValidLabel(label string) bool {
return len(label) <= maxLabel && labelRegex.Match([]byte(label))
}
// ValidKey returns true if the given key is valid, otherwise false.
func ValidKey(key string) bool {
return len(key) <= maxKey && keyRegex.Match([]byte(key))
}
func validateLabel(label string) error {
if ValidLabel(label) {
return nil
}
return ErrInvalidLabel
}
func validateKey(key string) error {
if ValidKey(key) {
return nil
}
return ErrInvalidKey
}

60
client/validate_test.go Normal file
View file

@ -0,0 +1,60 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
import "testing"
func TestValidateLabel(t *testing.T) {
labels := []string{
"a", "ab", "ab1", "d_e", "A", "Bc", "B1", "aB", "b-c",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
}
for _, label := range labels {
if validateLabel(label) != nil {
t.Fatalf("Should be valid label: %s", label)
}
}
}
func TestValidateLabelInvalid(t *testing.T) {
labels := []string{
"", "1", "_", "-", "'", "^", "/", "\\", "*", "a:b", "valid?no", "yüce",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1",
}
for _, label := range labels {
if validateLabel(label) == nil {
t.Fatalf("Should be invalid label: %s", label)
}
}
}
func TestValidateKey(t *testing.T) {
keys := []string{
"", "1", "ab", "ab1", "b-c", "d_e", "pilosa.com",
"bbf8d41c-7dba-40c4-94dc-94677b43bcf3", // UUID
"{bbf8d41c-7dba-40c4-94dc-94677b43bcf3}", // Windows GUID
"https%3A//www.pilosa.com/about/%23contact", // escaped URL
"aHR0cHM6Ly93d3cucGlsb3NhLmNvbS9hYm91dC8jY29udGFjdA==", // base64
"urn:isbn:1234567",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
}
for _, key := range keys {
if validateKey(key) != nil {
t.Fatalf("Should be valid key: %s", key)
}
}
}
func TestValidateKeyInvalid(t *testing.T) {
keys := []string{
"\"", "'", "slice\\dice", "valid?no", "yüce", "*xyz", "with space", "<script>",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1",
}
for _, key := range keys {
if validateKey(key) == nil {
t.Fatalf("Should be invalid key: %s", key)
}
}
}

8
client/version.go Normal file
View file

@ -0,0 +1,8 @@
// Copyright 2021 Molecula Corp. All rights reserved.
// package ctl contains all pilosa subcommands other than 'server'. These are
// generally administration, testing, and debugging tools.
package client
// Version is the client version.
const Version = "v1.3.0"

3031
cluster.go

File diff suppressed because it is too large Load diff

View file

@ -1,56 +1,37 @@
// 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 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"net/http/httptest"
"net/url"
"os"
"reflect"
"strconv"
"strings"
"testing"
"testing/quick"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/gorilla/mux"
"github.com/pilosa/pilosa/v2/logger"
"github.com/pilosa/pilosa/v2/roaring"
"github.com/pkg/errors"
pnet "github.com/molecula/featurebase/v3/net"
"github.com/molecula/featurebase/v3/roaring"
"github.com/molecula/featurebase/v3/testhook"
"github.com/molecula/featurebase/v3/topology"
. "github.com/molecula/featurebase/v3/vprint" // nolint:staticcheck
)
// Ensure that fragCombos creates the correct fragment mapping.
func TestFragCombos(t *testing.T) {
uri0, err := NewURIFromAddress("host0")
uri0, err := pnet.NewURIFromAddress("host0")
if err != nil {
t.Fatal(err)
}
uri1, err := NewURIFromAddress("host1")
uri1, err := pnet.NewURIFromAddress("host1")
if err != nil {
t.Fatal(err)
}
node0 := &Node{ID: "node0", URI: *uri0}
node1 := &Node{ID: "node1", URI: *uri1}
node0 := &topology.Node{ID: "node0", URI: *uri0}
node1 := &topology.Node{ID: "node1", URI: *uri1}
c := newCluster()
c.addNodeBasicSorted(node0)
@ -90,13 +71,37 @@ func TestFragCombos(t *testing.T) {
}
}
// newIndexWithTempPath returns a new instance of Index.
func newIndexWithTempPath(name string) *Index {
path, err := ioutil.TempDir(*TempDir, "pilosa-index-")
// newHolderWithTempPath returns a new instance of Holder.
func newHolderWithTempPath(tb testing.TB, backend string) *Holder {
path, err := testhook.TempDirInDir(tb, *TempDir, "pilosa-holder-")
if err != nil {
panic(err)
}
index, err := NewIndex(path, name)
cfg := mustHolderConfig()
cfg.StorageConfig.Backend = backend
h := NewHolder(path, cfg)
PanicOn(h.Open())
testhook.Cleanup(tb, func() {
h.Close()
})
return h
}
// newIndexWithTempPath returns a new instance of Index.
func newIndexWithTempPath(tb testing.TB, name string) *Index {
path, err := testhook.TempDirInDir(tb, *TempDir, "pilosa-index-")
if err != nil {
panic(err)
}
cfg := DefaultHolderConfig()
cfg.StorageConfig.FsyncEnabled = false
cfg.RBFConfig.FsyncEnabled = false
h := NewHolder(path, cfg)
PanicOn(h.Open())
index, err := h.CreateIndex(name, IndexOptions{})
testhook.Cleanup(tb, func() {
h.Close()
})
if err != nil {
panic(err)
}
@ -105,28 +110,27 @@ func newIndexWithTempPath(name string) *Index {
// Ensure that fragSources creates the correct fragment mapping.
func TestFragSources(t *testing.T) {
uri0, err := NewURIFromAddress("host0")
uri0, err := pnet.NewURIFromAddress("host0")
if err != nil {
t.Fatal(err)
}
uri1, err := NewURIFromAddress("host1")
uri1, err := pnet.NewURIFromAddress("host1")
if err != nil {
t.Fatal(err)
}
uri2, err := NewURIFromAddress("host2")
uri2, err := pnet.NewURIFromAddress("host2")
if err != nil {
t.Fatal(err)
}
uri3, err := NewURIFromAddress("host3")
uri3, err := pnet.NewURIFromAddress("host3")
if err != nil {
t.Fatal(err)
}
node0 := &Node{ID: "node0", URI: *uri0}
node1 := &Node{ID: "node1", URI: *uri1}
node2 := &Node{ID: "node2", URI: *uri2}
node3 := &Node{ID: "node3", URI: *uri3}
node0 := &topology.Node{ID: "node0", URI: *uri0}
node1 := &topology.Node{ID: "node1", URI: *uri1}
node2 := &topology.Node{ID: "node2", URI: *uri2}
node3 := &topology.Node{ID: "node3", URI: *uri3}
c1 := newCluster()
c1.ReplicaN = 1
@ -157,27 +161,53 @@ func TestFragSources(t *testing.T) {
c5.addNodeBasicSorted(node2)
c5.addNodeBasicSorted(node3)
idx := newIndexWithTempPath("i")
idx := newIndexWithTempPath(t, "i")
defer idx.Close()
field, err := idx.CreateFieldIfNotExists("f", OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
}
_, err = field.SetBit(1, 101, nil)
// Obtain transaction.
var shard uint64
tx := idx.holder.txf.NewTx(Txo{Write: writable, Index: idx, Shard: shard})
defer tx.Rollback()
_, err = field.SetBit(tx, 1, 101, nil)
if err != nil {
t.Fatal(err)
}
_, err = field.SetBit(1, ShardWidth+1, nil)
PanicOn(tx.Commit())
shard = 1
tx = idx.holder.txf.NewTx(Txo{Write: writable, Index: idx, Shard: shard})
defer tx.Rollback()
_, err = field.SetBit(tx, 1, ShardWidth*shard+1, nil)
if err != nil {
t.Fatal(err)
}
_, err = field.SetBit(1, ShardWidth*2+1, nil)
PanicOn(tx.Commit())
shard = 2
tx = idx.holder.txf.NewTx(Txo{Write: writable, Index: idx, Shard: shard})
defer tx.Rollback()
_, err = field.SetBit(tx, 1, ShardWidth*shard+1, nil)
if err != nil {
t.Fatal(err)
}
_, err = field.SetBit(1, ShardWidth*3+1, nil)
PanicOn(tx.Commit())
shard = 3
tx = idx.holder.txf.NewTx(Txo{Write: writable, Index: idx, Shard: shard})
defer tx.Rollback()
_, err = field.SetBit(tx, 1, ShardWidth*shard+1, nil)
if err != nil {
t.Fatal(err)
}
PanicOn(tx.Commit())
tests := []struct {
from *cluster
@ -194,8 +224,8 @@ func TestFragSources(t *testing.T) {
"node0": {},
"node1": {},
"node2": {
{&Node{ID: "node0", URI: URI{"http", "host0", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(0)},
{&Node{ID: "node1", URI: URI{"http", "host1", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(2)},
{&topology.Node{ID: "node0", URI: pnet.URI{Scheme: "http", Host: "host0", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(0)},
{&topology.Node{ID: "node1", URI: pnet.URI{Scheme: "http", Host: "host1", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(2)},
},
},
err: "",
@ -206,11 +236,11 @@ func TestFragSources(t *testing.T) {
idx: idx,
expected: map[string][]*ResizeSource{
"node0": {
{&Node{ID: "node1", URI: URI{"http", "host1", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(1)},
{&topology.Node{ID: "node1", URI: pnet.URI{Scheme: "http", Host: "host1", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(1)},
},
"node1": {
{&Node{ID: "node0", URI: URI{"http", "host0", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(0)},
{&Node{ID: "node0", URI: URI{"http", "host0", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(2)},
{&topology.Node{ID: "node0", URI: pnet.URI{Scheme: "http", Host: "host0", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(0)},
{&topology.Node{ID: "node0", URI: pnet.URI{Scheme: "http", Host: "host0", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(2)},
},
},
err: "",
@ -221,11 +251,11 @@ func TestFragSources(t *testing.T) {
idx: idx,
expected: map[string][]*ResizeSource{
"node0": {
{&Node{ID: "node2", URI: URI{"http", "host2", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(0)},
{&Node{ID: "node2", URI: URI{"http", "host2", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(2)},
{&topology.Node{ID: "node2", URI: pnet.URI{Scheme: "http", Host: "host2", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(0)},
{&topology.Node{ID: "node2", URI: pnet.URI{Scheme: "http", Host: "host2", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(2)},
},
"node1": {
{&Node{ID: "node0", URI: URI{"http", "host0", 10101}, IsCoordinator: false}, "i", "f", "standard", uint64(3)},
{&topology.Node{ID: "node0", URI: pnet.URI{Scheme: "http", Host: "host0", Port: 10101}, IsPrimary: false}, "i", "f", "standard", uint64(3)},
},
"node2": {},
},
@ -274,37 +304,37 @@ func TestFragSources(t *testing.T) {
// Ensure that fragSources creates the correct fragment mapping.
func TestResizeJob(t *testing.T) {
uri0, err := NewURIFromAddress("host0")
uri0, err := pnet.NewURIFromAddress("host0")
if err != nil {
t.Fatal(err)
}
uri1, err := NewURIFromAddress("host1")
uri1, err := pnet.NewURIFromAddress("host1")
if err != nil {
t.Fatal(err)
}
uri2, err := NewURIFromAddress("host2")
uri2, err := pnet.NewURIFromAddress("host2")
if err != nil {
t.Fatal(err)
}
node0 := &Node{ID: "node0", URI: *uri0}
node1 := &Node{ID: "node1", URI: *uri1}
node2 := &Node{ID: "node2", URI: *uri2}
node0 := &topology.Node{ID: "node0", URI: *uri0}
node1 := &topology.Node{ID: "node1", URI: *uri1}
node2 := &topology.Node{ID: "node2", URI: *uri2}
tests := []struct {
existingNodes []*Node
node *Node
existingNodes []*topology.Node
node *topology.Node
action string
expectedIDs map[string]bool
}{
{
existingNodes: []*Node{node0, node1},
existingNodes: []*topology.Node{node0, node1},
node: node2,
action: resizeJobActionAdd,
expectedIDs: map[string]bool{node0.ID: false, node1.ID: false, node2.ID: false},
},
{
existingNodes: []*Node{node0, node1, node2},
existingNodes: []*topology.Node{node0, node1, node2},
node: node2,
action: resizeJobActionRemove,
expectedIDs: map[string]bool{node0.ID: false, node1.ID: false},
@ -325,22 +355,27 @@ func TestResizeJob(t *testing.T) {
// Ensure the cluster can fairly distribute partitions across the nodes.
func TestCluster_Owners(t *testing.T) {
c := cluster{
nodes: []*Node{
noder: topology.NewLocalNoder([]*topology.Node{
{URI: NewTestURIFromHostPort("serverA", 1000)},
{URI: NewTestURIFromHostPort("serverB", 1000)},
{URI: NewTestURIFromHostPort("serverC", 1000)},
},
}),
Hasher: NewTestModHasher(),
ReplicaN: 2,
}
cNodes := c.noder.Nodes()
// Create a snapshot of the cluster to use for node/partition calculations.
snap := topology.NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
// Verify nodes are distributed.
if a := c.partitionNodes(0); !reflect.DeepEqual(a, []*Node{c.nodes[0], c.nodes[1]}) {
if a := snap.PartitionNodes(0); !reflect.DeepEqual(a, []*topology.Node{cNodes[0], cNodes[1]}) {
t.Fatalf("unexpected owners: %s", spew.Sdump(a))
}
// Verify nodes go around the ring.
if a := c.partitionNodes(2); !reflect.DeepEqual(a, []*Node{c.nodes[2], c.nodes[0]}) {
if a := snap.PartitionNodes(2); !reflect.DeepEqual(a, []*topology.Node{cNodes[2], cNodes[0]}) {
t.Fatalf("unexpected owners: %s", spew.Sdump(a))
}
}
@ -351,7 +386,7 @@ func TestCluster_Partition(t *testing.T) {
c := newCluster()
c.partitionN = partitionN
partitionID := c.partition(index, shard)
partitionID := topology.ShardToShardPartition(index, shard, partitionN)
if partitionID < 0 || partitionID >= partitionN {
t.Errorf("partition out of range: shard=%d, p=%d, n=%d", shard, partitionID, partitionN)
}
@ -381,7 +416,7 @@ func TestHasher(t *testing.T) {
{0x0ddc0ffeebadf00d, []int{0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15}},
} {
for i, v := range tt.bucket {
hasher := &jmphasher{}
hasher := &topology.Jmphasher{}
if got := hasher.Hash(tt.key, i+1); got != v {
t.Errorf("hash(%v,%v)=%v, want %v", tt.key, i+1, got, v)
}
@ -391,9 +426,14 @@ func TestHasher(t *testing.T) {
// Ensure ContainsShards can find the actual shard list for node and index.
func TestCluster_ContainsShards(t *testing.T) {
c := NewTestCluster(5)
c := NewTestCluster(t, 5)
c.ReplicaN = 3
shards := c.containsShards("test", roaring.NewBitmap(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), c.nodes[2])
cNodes := c.noder.Nodes()
// Create a snapshot of the cluster to use for node/partition calculations.
snap := topology.NewClusterSnapshot(c.noder, c.Hasher, c.ReplicaN)
shards := snap.ContainsShards("test", roaring.NewBitmap(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), cNodes[2])
if !reflect.DeepEqual(shards, []uint64{0, 2, 3, 5, 6, 9, 10}) {
t.Fatalf("unexpected shars for node's index: %v", shards)
@ -401,20 +441,22 @@ func TestCluster_ContainsShards(t *testing.T) {
}
func TestCluster_Nodes(t *testing.T) {
uri0 := NewTestURIFromHostPort("node0", 0)
uri1 := NewTestURIFromHostPort("node1", 0)
uri2 := NewTestURIFromHostPort("node2", 0)
uri3 := NewTestURIFromHostPort("node3", 0)
const urisCount = 4
var uris []pnet.URI
arbitraryPorts := []int{17384, 17385, 17386, 17387}
for i := 0; i < urisCount; i++ {
uris = append(uris, NewTestURIFromHostPort(fmt.Sprintf("node%d", i), uint16(arbitraryPorts[i])))
}
node0 := &Node{ID: "node0", URI: uri0}
node1 := &Node{ID: "node1", URI: uri1}
node2 := &Node{ID: "node2", URI: uri2}
node3 := &Node{ID: "node3", URI: uri3}
node0 := &topology.Node{ID: "node0", URI: uris[0]}
node1 := &topology.Node{ID: "node1", URI: uris[1]}
node2 := &topology.Node{ID: "node2", URI: uris[2]}
node3 := &topology.Node{ID: "node3", URI: uris[3]}
nodes := []*Node{node0, node1, node2}
nodes := []*topology.Node{node0, node1, node2}
t.Run("NodeIDs", func(t *testing.T) {
actual := Nodes(nodes).IDs()
actual := topology.Nodes(nodes).IDs()
expected := []string{node0.ID, node1.ID, node2.ID}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected: %v, but got: %v", expected, actual)
@ -422,24 +464,24 @@ func TestCluster_Nodes(t *testing.T) {
})
t.Run("Filter", func(t *testing.T) {
actual := Nodes(Nodes(nodes).Filter(nodes[1])).URIs()
expected := []URI{uri0, uri2}
actual := topology.Nodes(topology.Nodes(nodes).Filter(nodes[1])).URIs()
expected := []pnet.URI{uris[0], uris[2]}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected: %v, but got: %v", expected, actual)
}
})
t.Run("FilterURI", func(t *testing.T) {
actual := Nodes(Nodes(nodes).FilterURI(uri1)).URIs()
expected := []URI{uri0, uri2}
actual := topology.Nodes(topology.Nodes(nodes).FilterURI(uris[1])).URIs()
expected := []pnet.URI{uris[0], uris[2]}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected: %v, but got: %v", expected, actual)
}
})
t.Run("Contains", func(t *testing.T) {
actualTrue := Nodes(nodes).Contains(node1)
actualFalse := Nodes(nodes).Contains(node3)
actualTrue := topology.Nodes(nodes).Contains(node1)
actualFalse := topology.Nodes(nodes).Contains(node3)
if !reflect.DeepEqual(actualTrue, true) {
t.Errorf("expected: %v, but got: %v", true, actualTrue)
}
@ -449,9 +491,9 @@ func TestCluster_Nodes(t *testing.T) {
})
t.Run("Clone", func(t *testing.T) {
clone := Nodes(nodes).Clone()
actual := Nodes(clone).URIs()
expected := []URI{uri0, uri1, uri2}
clone := topology.Nodes(nodes).Clone()
actual := topology.Nodes(clone).URIs()
expected := []pnet.URI{uris[0], uris[1], uris[2]}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected: %v, but got: %v", expected, actual)
}
@ -459,9 +501,9 @@ func TestCluster_Nodes(t *testing.T) {
}
func TestCluster_PreviousNode(t *testing.T) {
node0 := &Node{ID: "node0"}
node1 := &Node{ID: "node1"}
node2 := &Node{ID: "node2"}
node0 := &topology.Node{ID: "node0"}
node1 := &topology.Node{ID: "node1"}
node2 := &topology.Node{ID: "node2"}
t.Run("OneNode", func(t *testing.T) {
c := newCluster()
@ -512,332 +554,6 @@ func TestCluster_PreviousNode(t *testing.T) {
})
}
// NEXT: move this test to internal and unexport IsCoordinator
func TestCluster_Coordinator(t *testing.T) {
uri1 := NewTestURIFromHostPort("node1", 0)
uri2 := NewTestURIFromHostPort("node2", 0)
node1 := &Node{ID: "node1", URI: uri1}
node2 := &Node{ID: "node2", URI: uri2}
c1 := *newCluster()
c1.Node = node1
c1.Coordinator = node1.ID
c2 := *newCluster()
c2.Node = node2
c2.Coordinator = node1.ID
t.Run("IsCoordinator", func(t *testing.T) {
if !c1.isCoordinator() {
t.Errorf("!IsCoordinator error: %v", c1.Node)
} else if c2.isCoordinator() {
t.Errorf("IsCoordinator error: %v", c2.Node)
}
})
}
func TestCluster_Topology(t *testing.T) {
c1 := NewTestCluster(1) // automatically creates Node{ID: "node0"}
uri0 := NewTestURIFromHostPort("host0", 0)
uri1 := NewTestURIFromHostPort("host1", 0)
uri2 := NewTestURIFromHostPort("host2", 0)
invalid := NewTestURIFromHostPort("invalid", 0)
node0 := &Node{ID: "node0", URI: uri0}
node1 := &Node{ID: "node1", URI: uri1}
node2 := &Node{ID: "node2", URI: uri2}
nodeinvalid := &Node{ID: "nodeinvalid", URI: invalid}
t.Run("AddNode", func(t *testing.T) {
err := c1.addNode(node1)
if err != nil {
t.Fatal(err)
}
// add the same host.
err = c1.addNode(node1)
if err != nil {
t.Fatal(err)
}
err = c1.addNode(node2)
if err != nil {
t.Fatal(err)
}
actual := c1.nodeIDs()
expected := []string{node0.ID, node1.ID, node2.ID}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected: %v, but got: %v", expected, actual)
}
})
t.Run("ContainsID", func(t *testing.T) {
if !c1.Topology.ContainsID(node1.ID) {
t.Errorf("!ContainsHost error: %v", node1.ID)
} else if c1.Topology.ContainsID(nodeinvalid.ID) {
t.Errorf("ContainsHost error: %v", nodeinvalid.ID)
}
})
}
// Ensure that general cluster functionality works as expected.
func TestCluster_ResizeStates(t *testing.T) {
t.Run("Single node, no data", func(t *testing.T) {
tc := NewClusterCluster(1)
// Open TestCluster.
if err := tc.Open(); err != nil {
t.Fatal(err)
}
node := tc.Clusters[0]
// Ensure that node comes up in state NORMAL.
if node.State() != ClusterStateNormal {
t.Errorf("expected state: %v, but got: %v", ClusterStateNormal, node.State())
}
expectedTop := &Topology{
nodeIDs: []string{node.Node.ID},
}
// Verify topology file.
if !reflect.DeepEqual(node.Topology.nodeIDs, expectedTop.nodeIDs) {
t.Errorf("expected topology: %v, but got: %v", expectedTop.nodeIDs, node.Topology.nodeIDs)
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
t.Run("Single node, in topology", func(t *testing.T) {
tc := NewClusterCluster(0)
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node := tc.Clusters[0]
// write topology to data file
top := &Topology{
nodeIDs: []string{node.Node.ID},
}
if err := tc.WriteTopology(node.Path, top); err != nil {
t.Fatalf("writing topology: %v", err)
}
// Open TestCluster.
if err := tc.Open(); err != nil {
t.Fatal(err)
}
// Ensure that node comes up in state NORMAL.
if node.State() != ClusterStateNormal {
t.Errorf("expected state: %v, but got: %v", ClusterStateNormal, node.State())
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
t.Run("Single node, not in topology", func(t *testing.T) {
tc := NewClusterCluster(0)
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node := tc.Clusters[0]
// write topology to data file
top := &Topology{
nodeIDs: []string{"some-other-host"},
}
if err := tc.WriteTopology(node.Path, top); err != nil {
t.Fatalf("writing topology: %v", err)
}
// Open TestCluster.
expected := "coordinator node0 is not in topology: [some-other-host]"
err := tc.Open()
if err == nil || errors.Cause(err).Error() != expected {
t.Errorf("did not receive expected error, got: %s", errors.Cause(err).Error())
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
t.Run("Multiple nodes, no data", func(t *testing.T) {
tc := NewClusterCluster(0)
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
// Open TestCluster.
if err := tc.Open(); err != nil {
t.Fatalf("opening cluster: %v", err)
}
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node0 := tc.Clusters[0]
node1 := tc.Clusters[1]
// Ensure that nodes comes up in state NORMAL.
if node0.State() != ClusterStateNormal {
t.Errorf("expected node0 state: %v, but got: %v", ClusterStateNormal, node0.State())
} else if node1.State() != ClusterStateNormal {
t.Errorf("expected node1 state: %v, but got: %v", ClusterStateNormal, node1.State())
}
expectedTop := &Topology{
nodeIDs: []string{node0.Node.ID, node1.Node.ID},
}
// Verify topology file.
if !reflect.DeepEqual(node0.Topology.nodeIDs, expectedTop.nodeIDs) {
t.Errorf("expected node0 topology: %v, but got: %v", expectedTop.nodeIDs, node0.Topology.nodeIDs)
} else if !reflect.DeepEqual(node1.Topology.nodeIDs, expectedTop.nodeIDs) {
t.Errorf("expected node1 topology: %v, but got: %v", expectedTop.nodeIDs, node1.Topology.nodeIDs)
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
t.Run("Multiple nodes, in/not in topology", func(t *testing.T) {
tc := NewClusterCluster(0)
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node0 := tc.Clusters[0]
// write topology to data file
top := &Topology{
nodeIDs: []string{"node0", "node2"},
}
if err := tc.WriteTopology(node0.Path, top); err != nil {
t.Fatalf("writing topology: %v", err)
}
// Open TestCluster.
if err := tc.Open(); err != nil {
t.Fatalf("opening cluster: %v", err)
}
// Ensure that node is in state STARTING before the other node joins.
if node0.State() != ClusterStateStarting {
t.Errorf("expected node0 state: %v, but got: %v", ClusterStateStarting, node0.State())
}
// Expect an error by adding a node not in the topology.
expectedError := "host is not in topology: node1"
if err := tc.addNode(); err == nil || err.Error() != expectedError {
t.Errorf("did not receive expected error: %s", expectedError)
}
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node2 := tc.Clusters[2]
// Ensure that node comes up in state NORMAL.
if node0.State() != ClusterStateNormal {
t.Errorf("expected node0 state: %v, but got: %v", ClusterStateNormal, node0.State())
} else if node2.State() != ClusterStateNormal {
t.Errorf("expected node2 state: %v, but got: %v", ClusterStateNormal, node2.State())
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
t.Run("Multiple nodes, with data", func(t *testing.T) {
tc := NewClusterCluster(0)
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node0 := tc.Clusters[0]
// Open TestCluster.
if err := tc.Open(); err != nil {
t.Fatal(err)
}
// Add Bit Data to node0.
if err := tc.CreateField("i", "f", OptFieldTypeDefault()); err != nil {
t.Fatalf("creating field: %v", err)
}
if err := tc.SetBit("i", "f", 1, 101, nil); err != nil {
t.Fatalf("setting bit: %v", err)
}
if err := tc.SetBit("i", "f", 1, ShardWidth+1, nil); err != nil {
t.Fatalf("setting bit: %v", err)
}
// Before starting the resize, get the CheckSum to use for
// comparison later.
node0Field := node0.holder.Field("i", "f")
node0View := node0Field.view("standard")
node0Fragment := node0View.Fragment(1)
node0Checksum := node0Fragment.Checksum()
// addNode needs to block until the resize process has completed.
if err := tc.addNode(); err != nil {
t.Fatalf("adding node: %v", err)
}
node1 := tc.Clusters[1]
// Ensure that nodes come up in state NORMAL.
if node0.State() != ClusterStateNormal {
t.Errorf("expected node0 state: %v, but got: %v", ClusterStateNormal, node0.State())
} else if node1.State() != ClusterStateNormal {
t.Errorf("expected node1 state: %v, but got: %v", ClusterStateNormal, node1.State())
}
expectedTop := &Topology{
nodeIDs: []string{node0.Node.ID, node1.Node.ID},
}
// Verify topology file.
if !reflect.DeepEqual(node0.Topology.nodeIDs, expectedTop.nodeIDs) {
t.Errorf("expected node0 topology: %v, but got: %v", expectedTop.nodeIDs, node0.Topology.nodeIDs)
} else if !reflect.DeepEqual(node1.Topology.nodeIDs, expectedTop.nodeIDs) {
t.Errorf("expected node1 topology: %v, but got: %v", expectedTop.nodeIDs, node1.Topology.nodeIDs)
}
// Bits
// Verify that node-1 contains the fragment (i/f/standard/1) transferred from node-0.
node1Field := node1.holder.Field("i", "f")
node1View := node1Field.view("standard")
node1Fragment := node1View.Fragment(1)
// Ensure checksums are the same.
if chksum := node1Fragment.Checksum(); !bytes.Equal(chksum, node0Checksum) {
t.Fatalf("expected standard view checksum to match: %x - %x", chksum, node0Checksum)
}
// Close TestCluster.
if err := tc.Close(); err != nil {
t.Fatal(err)
}
})
}
func TestAE(t *testing.T) {
t.Run("AbortDoesn'tBlockUninitialized", func(t *testing.T) {
c := newCluster()
@ -846,6 +562,7 @@ func TestAE(t *testing.T) {
c.abortAntiEntropy()
close(ch)
}()
defer c.abortAntiEntropyQ() // avoid leaking a goroutine.
select {
case <-ch:
return
@ -857,11 +574,13 @@ func TestAE(t *testing.T) {
t.Run("AbortBlocksInitialized", func(t *testing.T) {
c := newCluster()
c.initializeAntiEntropy()
ch := make(chan struct{})
go func() {
c.abortAntiEntropy()
close(ch)
}()
defer c.abortAntiEntropyQ() // avoid leak of goroutine.
select {
case <-ch:
t.Fatalf("aborting anti entropy on an initialized cluster didn't block")
@ -893,97 +612,15 @@ func TestAE(t *testing.T) {
t.Fatalf("abort should not have blocked this long")
}
})
}
// Ensures that coordinator can be changed.
func TestCluster_UpdateCoordinator(t *testing.T) {
t.Run("UpdateCoordinator", func(t *testing.T) {
c := NewTestCluster(2)
oldNode := c.nodes[0]
newNode := c.nodes[1]
// Update coordinator to the same value.
if c.updateCoordinator(oldNode) {
t.Errorf("did not expect coordinator to change")
} else if c.Coordinator != oldNode.ID {
t.Errorf("expected coordinator: %s, but got: %s", c.Coordinator, oldNode.URI)
}
// Update coordinator to a new value.
if !c.updateCoordinator(newNode) {
t.Errorf("expected coordinator to change")
} else if c.Coordinator != newNode.ID {
t.Errorf("expected coordinator: %s, but got: %s", c.Coordinator, newNode.URI)
}
})
}
func TestCluster_confirmNodeDownUp(t *testing.T) {
r := mux.NewRouter()
r.HandleFunc("/version", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "ignored")
}))
server := httptest.NewServer(r)
// Close the server when test finishes
defer server.Close()
u, err := url.Parse(server.URL)
if err != nil {
t.Error("bad test setup")
}
uri := URI{}
host, port, _ := net.SplitHostPort(u.Host)
uri.Scheme = u.Scheme
uri.Host = host
iport, err := strconv.ParseUint(port, 0, 16)
if err != nil {
t.Error(err)
}
uri.Port = uint16(iport)
if confirmNodeDown(uri, logger.NewVerboseLogger(os.Stdout)) {
t.Errorf("expected node to be up")
}
}
func TestCluster_confirmNodeDownTimeout(t *testing.T) {
r := mux.NewRouter()
r.HandleFunc("/version", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(confirmDownSleep * time.Second * confirmDownRetries)
fmt.Fprintln(w, "ignored")
}))
server := httptest.NewServer(r)
// Close the server when test finishes
defer server.Close()
u, err := url.Parse(server.URL)
if err != nil {
t.Error("bad test setup")
}
uri := URI{}
host, port, _ := net.SplitHostPort(u.Host)
uri.Scheme = u.Scheme
uri.Host = host
iport, err := strconv.ParseUint(port, 0, 16)
if err != nil {
t.Error(err)
}
uri.Port = uint16(iport)
if !confirmNodeDown(uri, logger.NewVerboseLogger(os.Stdout)) {
t.Errorf("expected node to be down")
}
}
func TestCluster_confirmNodeDownDown(t *testing.T) {
uri := URI{}
uri.Scheme = "http"
uri.Host = "DoesntMatter"
uri.Port = 6666
if !confirmNodeDown(uri, logger.NewVerboseLogger(os.Stdout)) {
t.Errorf("expected node to be down")
}
func TestTranslateIndexKey(t *testing.T) {
c := newCluster()
node0 := &topology.Node{ID: "node0"}
c.addNodeBasicSorted(node0)
c.holder = newHolderWithTempPath(t, "rbf")
_, e := c.translateIndexKey(context.Background(), "i", "a", false)
if e == nil {
t.Fatal("expecting error")
}
}

24
cmd.go
View file

@ -1,22 +1,10 @@
// 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 2021 Molecula Corp. All rights reserved.
package pilosa
import (
"io"
"log"
"github.com/molecula/featurebase/v3/logger"
)
// CmdIO holds standard unix inputs and outputs.
@ -24,7 +12,7 @@ type CmdIO struct {
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
logger *log.Logger
logger logger.Logger
}
// NewCmdIO returns a new instance of CmdIO with inputs and outputs set to the
@ -34,10 +22,10 @@ func NewCmdIO(stdin io.Reader, stdout, stderr io.Writer) *CmdIO {
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
logger: log.New(stderr, "", log.LstdFlags),
logger: logger.NewStandardLogger(stderr),
}
}
func (c *CmdIO) Logger() *log.Logger {
func (c *CmdIO) Logger() logger.Logger {
return c.logger
}

36
cmd/backup.go Normal file
View file

@ -0,0 +1,36 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package cmd
import (
"context"
"io"
"github.com/molecula/featurebase/v3/ctl"
"github.com/spf13/cobra"
)
func newBackupCommand(stdin io.Reader, stdout io.Writer, stderr io.Writer) *cobra.Command {
cmd := ctl.NewBackupCommand(stdin, stdout, stderr)
ccmd := &cobra.Command{
Use: "backup",
Short: "Back up FeatureBase server",
Long: `
Backs up a FeatureBase server to a local, tar-formatted snapshot file.
`,
RunE: func(c *cobra.Command, args []string) error {
return cmd.Run(context.Background())
},
}
flags := ccmd.Flags()
flags.StringVarP(&cmd.OutputDir, "output", "o", "", "Output directory to write to.")
flags.BoolVar(&cmd.NoSync, "no-sync", false, "Disable file sync")
flags.IntVar(&cmd.Concurrency, "concurrency", cmd.Concurrency, "Number of concurrent backup goroutines.")
flags.StringVar(&cmd.Host, "host", "localhost:10101", "The address (host:port) of FeatureBase (HTTP).")
flags.StringVar(&cmd.Index, "index", "", "Index to backup, default backs up all indexes. ")
flags.DurationVar(&cmd.RetryPeriod, "retry-period", cmd.RetryPeriod, "Length of time after HTTP request failure to continue retrying request.")
flags.StringVar(&cmd.Pprof, "pprof", cmd.Pprof, "host:port to listen for profiling requests at /debug/pprof and /debug/fgprof.")
ctl.SetTLSConfig(flags, "", &cmd.TLS.CertificatePath, &cmd.TLS.CertificateKeyPath, &cmd.TLS.CACertPath, &cmd.TLS.SkipVerify, &cmd.TLS.EnableClientVerification)
flags.StringVar(&cmd.AuthToken, "auth-token", "", "Authentication token")
return ccmd
}

137
cmd/badloader/badloader.go Normal file
View file

@ -0,0 +1,137 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package main
import (
"archive/tar"
"compress/gzip"
"context"
"time"
"fmt"
"io"
"io/ioutil"
gohttp "net/http"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/encoding/proto"
pnet "github.com/molecula/featurebase/v3/net"
"github.com/molecula/featurebase/v3/vprint"
"os"
"strconv"
"strings"
)
func UploadTar(srcFile string, client *pilosa.InternalClient) error {
t0 := time.Now()
f, err := os.Open(srcFile)
if err != nil {
return (err)
}
defer f.Close()
var tarReader *tar.Reader
if strings.HasSuffix(srcFile, "gz") {
gzf, err := gzip.NewReader(f)
if err != nil {
return err
}
tarReader = tar.NewReader(gzf)
} else {
tarReader = tar.NewReader(f)
}
viewData := make(map[string][]byte)
//given ordered by index/field/view
//trait_store/product_count__commercial_cd_or_share_certificate/views/bsig_product_count__commercial_cd_or_share_certificate/fragments/255
lastIndex := ""
lastField := ""
lastShard := uint64(0)
n := 0
for {
header, err := tarReader.Next()
if err == io.EOF {
if header != nil {
vprint.PanicOn("header should not be nil on err io.EOF")
}
//submit any stuff we have left
if len(viewData) > 0 {
request := &pilosa.ImportRoaringRequest{
Views: viewData,
}
// Submit(lastIndex, lastField, lastShard, request)
uri := GetImportRoaringURI(lastIndex, lastShard)
err := client.ImportRoaring(context.Background(), uri, lastIndex, lastField, lastShard, false, request)
vprint.PanicOn(err)
}
return nil
}
n++
if n%500 == 0 {
vprint.VV("n = %v, progress, elapsed '%v'", n, time.Since(t0))
}
parts := strings.Split(header.Name, "/")
//vv("parts = '%#v'", parts)
index := parts[1]
field := parts[2]
view := parts[4]
shard, err := strconv.ParseUint(parts[6], 10, 64)
if err != nil {
return err
}
// TODO: shards can be loaded in parallel, so maybe farm out to a worker set of goro.
if index != lastIndex || field != lastField || shard != lastShard {
if len(viewData) > 0 {
request := &pilosa.ImportRoaringRequest{
Views: viewData,
}
//vv("about to submit lastIndex='%v' lastShard='%v'", lastIndex, lastShard)
uri := GetImportRoaringURI(lastIndex, lastShard)
vprint.PanicOn(client.ImportRoaring(context.Background(), uri, lastIndex, lastField, lastShard, false, request))
viewData = make(map[string][]byte)
//vv("done with submit lastIndex='%v' lastShard='%v'; took='%v'", lastIndex, lastShard, time.Since(t0))
}
}
roaringData, err := ioutil.ReadAll(tarReader)
if err != nil {
return err
}
if _, already := viewData[view]; already {
vprint.PanicOn(fmt.Sprintf("view '%v' already present!", view))
}
viewData[view] = roaringData
lastIndex = index
lastField = field
//lastShard = shard
//vv("bottom of loop")
}
}
// badloader reproduce a union in place issue for us. slurp is
// the new "good" loader, and should always be preferred now
// when not trying to repro that bug. pulled from 85fa67e8
func main() {
host := "127.0.0.1:10101"
h := &gohttp.Client{}
c, err := pilosa.NewInternalClient(host, h, pilosa.WithSerializer(proto.Serializer{}))
vprint.PanicOn(err)
tarSrcPath := "q2.tar.gz"
t0 := time.Now()
vprint.PanicOn(UploadTar(tarSrcPath, c))
vprint.VV("total elapsed '%v'", time.Since(t0))
}
var globURI *pnet.URI
func init() {
var err error
globURI, err = pnet.NewURIFromHostPort("127.0.0.1", 10101)
vprint.PanicOn(err)
}
// get correct node to go to.
func GetImportRoaringURI(index string, shard uint64) *pnet.URI {
return globURI
}

View file

@ -1,46 +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 cmd
import (
"context"
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/pilosa/pilosa/v2/ctl"
)
var checker *ctl.CheckCommand
func newCheckCommand(stdin io.Reader, stdout io.Writer, stderr io.Writer) *cobra.Command {
checker = ctl.NewCheckCommand(stdin, stdout, stderr)
checkCmd := &cobra.Command{
Use: "check <path> [path2]...",
Short: "Do a consistency check on a pilosa data file.",
Long: `
Performs a consistency check on data files.
`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("path required")
}
checker.Paths = args
return checker.Run(context.Background())
},
}
return checkCmd
}

View file

@ -1,36 +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 cmd_test
import (
"strings"
"testing"
)
func TestCheckHelp(t *testing.T) {
output, err := ExecNewRootCommand(t, "check", "--help")
if !strings.Contains(output, "Usage:") ||
!strings.Contains(output, "Flags:") ||
!strings.Contains(output, "pilosa check") || err != nil {
t.Fatalf("Command 'check --help' not working, err: '%v', output: '%s'", err, output)
}
}
func TestCheckNoPath(t *testing.T) {
output, err := ExecNewRootCommand(t, "check")
if !strings.Contains(err.Error(), "path required") {
t.Fatalf("Command 'check' without args should error but: err: '%v', output: '%v'", err, output)
}
}

30
cmd/chksum.go Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package cmd
import (
"context"
"io"
"github.com/molecula/featurebase/v3/ctl"
"github.com/spf13/cobra"
)
func newChkSumCommand(stdin io.Reader, stdout io.Writer, stderr io.Writer) *cobra.Command {
cmd := ctl.NewChkSumCommand(stdin, stdout, stderr)
ccmd := &cobra.Command{
Use: "chksum",
Short: "Digital signature of FeatureBase data",
Long: `
Generates a digital signature of all the data associated with a provided FeatureBase server
WARNING: could be slow if high cardinality fields exist
`,
RunE: func(c *cobra.Command, args []string) error {
return cmd.Run(context.Background())
},
}
flags := ccmd.Flags()
flags.StringVar(&cmd.Host, "host", "localhost:10101", "host:port of FeatureBase.")
ctl.SetTLSConfig(flags, "", &cmd.TLS.CertificatePath, &cmd.TLS.CertificateKeyPath, &cmd.TLS.CACertPath, &cmd.TLS.SkipVerify, &cmd.TLS.EnableClientVerification)
return ccmd
}

View file

@ -1,17 +1,4 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd
import (
@ -20,8 +7,8 @@ import (
"github.com/spf13/cobra"
"github.com/pilosa/pilosa/v2/ctl"
"github.com/pilosa/pilosa/v2/server"
"github.com/molecula/featurebase/v3/ctl"
"github.com/molecula/featurebase/v3/server"
)
var conf *ctl.ConfigCommand

View file

@ -1,17 +1,4 @@
// 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 2021 Molecula Corp. All rights reserved.
/*
Package cmd contains all the pilosa subcommand definitions (1 per file).

View file

@ -1,17 +1,4 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd
import (
@ -20,7 +7,7 @@ import (
"github.com/spf13/cobra"
"github.com/pilosa/pilosa/v2/ctl"
"github.com/molecula/featurebase/v3/ctl"
)
var Exporter *ctl.ExportCommand
@ -29,7 +16,7 @@ func newExportCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command
Exporter = ctl.NewExportCommand(stdin, stdout, stderr)
exportCmd := &cobra.Command{
Use: "export",
Short: "Export data from pilosa.",
Short: "Export data from FeatureBase.",
Long: `
Bulk exports a fragment to a CSV file. If the OUTFILE is not specified then
the output is written to STDOUT.
@ -46,11 +33,11 @@ The file does not contain any headers.
}
flags := exportCmd.Flags()
flags.StringVarP(&Exporter.Host, "host", "", "localhost:10101", "host:port of Pilosa.")
flags.StringVarP(&Exporter.Index, "index", "i", "", "Pilosa index to export")
flags.StringVarP(&Exporter.Host, "host", "", "localhost:10101", "host:port of FeatureBase.")
flags.StringVarP(&Exporter.Index, "index", "i", "", "FeatureBase index to export")
flags.StringVarP(&Exporter.Field, "field", "f", "", "Field to export")
flags.StringVarP(&Exporter.Path, "output-file", "o", "", "File to write export to - default stdout")
ctl.SetTLSConfig(flags, &Exporter.TLS.CertificatePath, &Exporter.TLS.CertificateKeyPath, &Exporter.TLS.CACertPath, &Exporter.TLS.SkipVerify, &Exporter.TLS.EnableClientVerification)
ctl.SetTLSConfig(flags, "", &Exporter.TLS.CertificatePath, &Exporter.TLS.CertificateKeyPath, &Exporter.TLS.CACertPath, &Exporter.TLS.SkipVerify, &Exporter.TLS.EnableClientVerification)
return exportCmd
}

View file

@ -1,31 +1,18 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd_test
import (
"strings"
"testing"
"github.com/pilosa/pilosa/v2/cmd"
"github.com/molecula/featurebase/v3/cmd"
)
func TestExportHelp(t *testing.T) {
output, err := ExecNewRootCommand(t, "export", "--help")
if !strings.Contains(output, "Usage:") ||
!strings.Contains(output, "Flags:") ||
!strings.Contains(output, "pilosa export") || err != nil {
!strings.Contains(output, "featurebase export") || err != nil {
t.Fatalf("Command 'export --help' not working, err: '%v', output: '%s'", err, output)
}
}

View file

@ -0,0 +1,47 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"strings"
"github.com/molecula/featurebase/v3/sql2"
)
func main() {
if err := run(context.Background(), os.Args[1:]); err == flag.ErrHelp {
os.Exit(1)
} else if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func run(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("featurebase-parse-sql", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
return err
}
q := fs.Arg(0)
if q == "" {
return fmt.Errorf("query required")
}
stmt, err := sql2.NewParser(strings.NewReader(q)).ParseStatement()
if err != nil {
return err
}
buf, err := json.MarshalIndent(stmt, "", " ")
if err != nil {
return err
}
fmt.Println(string(buf))
return nil
}

20
cmd/featurebase/main.go Normal file
View file

@ -0,0 +1,20 @@
// Copyright 2021 Molecula Corp. All rights reserved.
/*
This is the entrypoint for the Pilosa binary.
*/
package main
import (
"fmt"
"os"
"github.com/molecula/featurebase/v3/cmd"
)
func main() {
rootCmd := cmd.NewRootCommand(os.Stdin, os.Stdout, os.Stderr)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

View file

@ -0,0 +1,13 @@
//go:build testrunmain
// +build testrunmain
package main
import (
"testing"
)
// Wrapper test for main function used to get code coverage for end2end tests
func TestRunMain(t *testing.T) {
main()
}

View file

@ -1,17 +1,4 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd
import (
@ -20,7 +7,7 @@ import (
"github.com/spf13/cobra"
"github.com/pilosa/pilosa/v2/ctl"
"github.com/molecula/featurebase/v3/ctl"
)
var generateConf *ctl.GenerateConfigCommand

View file

@ -1,36 +1,23 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd
import (
"context"
"io"
"github.com/pilosa/pilosa/v2"
"github.com/pilosa/pilosa/v2/ctl"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/ctl"
"github.com/spf13/cobra"
)
var Importer *ctl.ImportCommand
// newImportCommand runs the Pilosa import subcommand for ingesting bulk data.
// newImportCommand runs the FeatureBase import subcommand for ingesting bulk data.
func newImportCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command {
Importer = ctl.NewImportCommand(stdin, stdout, stderr)
importCmd := &cobra.Command{
Use: "import",
Short: "Bulk load data into pilosa.",
Short: "Bulk load data into FeatureBase.",
Long: `Bulk imports one or more CSV files to a host's index and field. The data
of the CSV file are grouped by shard for the most efficient import.
@ -48,14 +35,14 @@ omitted. If it is present then its format should be YYYY-MM-DDTHH:MM.
}
flags := importCmd.Flags()
flags.StringVarP(&Importer.Host, "host", "", "localhost:10101", "host:port of Pilosa.")
flags.StringVarP(&Importer.Index, "index", "i", "", "Pilosa index to import into.")
flags.StringVarP(&Importer.Host, "host", "", "localhost:10101", "host:port of FeatureBase.")
flags.StringVarP(&Importer.Index, "index", "i", "", "FeatureBase index to import into.")
flags.StringVarP(&Importer.Field, "field", "f", "", "Field to import into.")
flags.BoolVar(&Importer.IndexOptions.Keys, "index-keys", false, "Specify keys=true when creating an index")
flags.BoolVar(&Importer.FieldOptions.Keys, "field-keys", false, "Specify keys=true when creating a field")
flags.StringVar(&Importer.FieldOptions.Type, "field-type", "", "Specify the field type when creating a field. One of: set, int, time, bool, mutex")
flags.Int64Var(&Importer.FieldOptions.Min, "field-min", 0, "Specify the minimum for an int field on creation")
flags.Int64Var(&Importer.FieldOptions.Max, "field-max", 0, "Specify the maximum for an int field on creation")
flags.StringVar(&Importer.FieldOptions.Type, "field-type", "", "Specify the field type when creating a field. One of: set, int, decimal, time, bool, mutex")
flags.Int64Var(&Importer.FieldOptions.Min.Value, "field-min", 0, "Specify the minimum for an int field on creation") // TODO: noting that decimal field min/max are not supported here.
flags.Int64Var(&Importer.FieldOptions.Max.Value, "field-max", 0, "Specify the maximum for an int field on creation")
flags.StringVar(&Importer.FieldOptions.CacheType, "field-cache-type", pilosa.CacheTypeRanked, "Specify the cache type for a set field on creation. One of: none, lru, ranked")
flags.Uint32Var(&Importer.FieldOptions.CacheSize, "field-cache-size", 50000, "Specify the cache size for a set field on creation")
flags.Var(&Importer.FieldOptions.TimeQuantum, "field-time-quantum", "Specify the time quantum for a time field on creation. One of: D, DH, H, M, MD, MDH, Y, YM, YMD, YMDH")
@ -63,7 +50,8 @@ omitted. If it is present then its format should be YYYY-MM-DDTHH:MM.
flags.BoolVarP(&Importer.Sort, "sort", "", false, "Enables sorting before import.")
flags.BoolVarP(&Importer.CreateSchema, "create", "e", false, "Create the schema if it does not exist before import.")
flags.BoolVarP(&Importer.Clear, "clear", "", false, "Clear the data provided in the import.")
ctl.SetTLSConfig(flags, &Importer.TLS.CertificatePath, &Importer.TLS.CertificateKeyPath, &Importer.TLS.CACertPath, &Importer.TLS.SkipVerify, &Importer.TLS.EnableClientVerification)
ctl.SetTLSConfig(flags, "", &Importer.TLS.CertificatePath, &Importer.TLS.CertificateKeyPath, &Importer.TLS.CACertPath, &Importer.TLS.SkipVerify, &Importer.TLS.EnableClientVerification)
flags.StringVar(&Importer.AuthToken, "auth-token", "", "Authentication token")
return importCmd
}

View file

@ -1,33 +1,21 @@
// 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 2021 Molecula Corp. All rights reserved.
package cmd_test
import (
"strings"
"testing"
"github.com/pilosa/pilosa/v2"
"github.com/molecula/featurebase/v3"
"github.com/pilosa/pilosa/v2/cmd"
"github.com/molecula/featurebase/v3/cmd"
"github.com/molecula/featurebase/v3/pql"
)
func TestImportHelp(t *testing.T) {
output, err := ExecNewRootCommand(t, "import", "--help")
if !strings.Contains(output, "Usage:") ||
!strings.Contains(output, "Flags:") ||
!strings.Contains(output, "pilosa import") || err != nil {
!strings.Contains(output, "featurebase import") || err != nil {
t.Fatalf("Command 'import --help' not working, err: '%v', output: '%s'", err, output)
}
}
@ -58,8 +46,8 @@ field = "f1"
v.Check(cmd.Importer.Field, "f1")
v.Check(cmd.Importer.FieldOptions, pilosa.FieldOptions{
Keys: true,
Max: 100,
Min: -10,
Max: pql.NewDecimal(100, 0),
Min: pql.NewDecimal(-10, 0),
CacheType: pilosa.CacheTypeRanked,
CacheSize: 50000,
})

View file

@ -1,49 +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 cmd
import (
"context"
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/pilosa/pilosa/v2/ctl"
)
var inspector *ctl.InspectCommand
func newInspectCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command {
inspector = ctl.NewInspectCommand(stdin, stdout, stderr)
inspectCmd := &cobra.Command{
Use: "inspect",
Short: "Get stats on a pilosa data file.",
Long: `
Inspects a data file and provides stats.
`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("path required")
} else if len(args) > 1 {
return fmt.Errorf("only one path allowed")
}
inspector.Path = args[0]
return inspector.Run(context.Background())
},
}
return inspectCmd
}

View file

@ -1,42 +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 cmd_test
import (
"strings"
"testing"
)
func TestInspectHelp(t *testing.T) {
output, err := ExecNewRootCommand(t, "inspect", "--help")
if !strings.Contains(output, "Usage:") ||
!strings.Contains(output, "pilosa inspect") || err != nil {
t.Fatalf("Command 'inspect --help' not working, err: '%v', output: '%s'", err, output)
}
}
func TestInspectNoPath(t *testing.T) {
output, err := ExecNewRootCommand(t, "inspect")
if !strings.Contains(err.Error(), "path required") {
t.Fatalf("Command 'inspect' without args should error but: err: '%v', output: '%v'", err, output)
}
}
func TestInspectMultiPath(t *testing.T) {
output, err := ExecNewRootCommand(t, "inspect", "one", "two")
if !strings.Contains(err.Error(), "only one path") {
t.Fatalf("Command 'inspect' without args should error but: err: '%v', output: '%v'", err, output)
}
}

28
cmd/keygen.go Normal file
View file

@ -0,0 +1,28 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package cmd
import (
"context"
"io"
"github.com/molecula/featurebase/v3/ctl"
"github.com/spf13/cobra"
)
func newKeygenCommand(stdin io.Reader, stdout io.Writer, stderr io.Writer) *cobra.Command {
cmd := ctl.NewKeygenCommand(stdin, stdout, stderr)
ccmd := &cobra.Command{
Use: "keygen",
Short: "Generate secret key for authentication.",
Long: `
Generate secret key to configure FeatureBase for Authentication.
`,
RunE: func(c *cobra.Command, args []string) error {
return cmd.Run(context.Background())
},
}
flags := ccmd.Flags()
flags.IntVarP(&cmd.KeyLength, "length", "l", 32, "length of the key to produce")
return ccmd
}

345
cmd/pilosa-bench/main.go Normal file
View file

@ -0,0 +1,345 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package main
import (
"context"
"expvar"
"flag"
"fmt"
"io/ioutil"
"log"
"math/rand"
"net/http"
_ "net/http/pprof"
"os"
"sort"
"strings"
"time"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/encoding/proto"
"golang.org/x/sync/errgroup"
)
var (
requestCountVar = expvar.NewInt("request_count")
requestCurrentLatencyVar = expvar.NewFloat("request_current_latency") // seconds
requestAvgLatencyVar = expvar.NewFloat("request_avg_latency") // seconds
requestTotalLatencyVar = expvar.NewFloat("request_total_latency") // seconds
requestPerSecVar = expvar.NewFloat("request_per_sec")
)
func main() {
if err := run(context.Background(), os.Args[1:]); err == flag.ErrHelp {
os.Exit(1)
} else if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func run(ctx context.Context, args []string) (err error) {
fs := flag.NewFlagSet("pilosa-bench", flag.ContinueOnError)
hostport := fs.String("hostport", "localhost:10101", "")
typ := fs.String("type", "row", "query type (row)")
n := fs.Int("n", 1000, "number of queries")
rate := fs.Int("rate", 1, "number of queries per second")
verbose := fs.Bool("v", false, "verbose logging")
from := fs.String("from", "", "from time for row-range queries (ISO 8601)")
to := fs.String("to", "", "to time for row-range queries (ISO 8601)")
if err := fs.Parse(args); err != nil {
return err
}
// Parse from/to time.
var opt queryOptions
if *from != "" {
if opt.from, err = time.Parse(time.RFC3339, *from); err != nil {
return fmt.Errorf("cannot parse -from time")
}
}
if *to != "" {
if opt.to, err = time.Parse(time.RFC3339, *to); err != nil {
return fmt.Errorf("cannot parse -to time")
}
}
if (*typ == "row-range" || *typ == "topk") && (opt.from.IsZero() || opt.to.IsZero()) {
return fmt.Errorf("-from and -to flags must be specified for topk & row-range queries")
}
// Clear time prefix on log.
log.SetFlags(0)
if !*verbose {
log.SetOutput(ioutil.Discard)
}
// Setup PRNG to have consistent values for the same set of data.
rand.Seed(0)
// Setup connection to pilosa.
client, err := pilosa.NewInternalClient(*hostport, http.DefaultClient, pilosa.WithSerializer(proto.Serializer{}))
if err != nil {
return err
}
// Set up HTTP endpoint to provide /debug endpoints.
fmt.Println("Serving debug endpoint at http://localhost:7070/debug")
go func() { _ = http.ListenAndServe(":7070", nil) }()
// Run separate goroutine to calculate the current req/sec & latency.
go monitor()
// Load all id/keys for each field.
log.Printf("loading field identifiers")
fieldIDMap, err := loadFields(ctx, client)
if err != nil {
return fmt.Errorf("cannot load field identifiers: %w", err)
} else if len(fieldIDMap) == 0 {
return fmt.Errorf("no field identifiers available, please verify data exists")
}
// Generate list of sorted keys.
fieldKeys := make([]fieldKey, 0, len(fieldIDMap))
for k, f := range fieldIDMap {
switch *typ {
case "row-bsi":
if f.info.Options.Type != "int" {
continue
}
case "row-range", "topk":
if f.info.Options.Type != "time" {
continue
}
default:
if f.info.Options.Type == "int" || f.info.Options.Type == "time" {
continue
}
}
fieldKeys = append(fieldKeys, k)
}
sort.Slice(fieldKeys, func(i, j int) bool {
return compareFieldKeys(fieldKeys[i], fieldKeys[j]) == -1
})
// Ensure we have appropriate fields for our query type.
if len(fieldKeys) == 0 {
return fmt.Errorf("no available fields are appropriate for %q queries", *typ)
}
log.Printf("issuing %d queries at %d query/sec", *n, *rate)
// Repeatedly issue queries based on available row data.
ticker := time.NewTicker(time.Second / time.Duration(*rate))
var g errgroup.Group
for i := 0; i < *n; i++ {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
}
key := fieldKeys[rand.Intn(len(fieldKeys))]
q, err := generateQuery(*typ, key.index, key.field, fieldIDMap[key].info, fieldIDMap[key].identifiers, opt)
if err != nil {
return fmt.Errorf("cannot generate query: %w", err)
}
log.Printf("[query] %s", q)
g.Go(func() error {
t := time.Now()
_, err = client.Query(ctx, key.index, &pilosa.QueryRequest{Index: key.index, Query: q})
if err != nil {
return err
}
elapsed := time.Since(t).Seconds()
requestCountVar.Add(1)
requestTotalLatencyVar.Add(elapsed)
requestAvgLatencyVar.Set(requestTotalLatencyVar.Value() / float64(requestCountVar.Value()))
return nil
})
}
return g.Wait()
}
// monitor runs in a separate goroutine and updates metrics.
func monitor() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
var lastTime time.Time
var lastN int64
var lastLatency float64
for range ticker.C {
now, n := time.Now(), requestCountVar.Value()
latency := requestTotalLatencyVar.Value()
if !lastTime.IsZero() {
elapsed := lastTime.Sub(now).Seconds()
if n > 0 {
requestCurrentLatencyVar.Set((lastLatency - latency) / float64(n))
}
requestPerSecVar.Set(float64(lastN-n) / elapsed)
}
lastTime, lastN, lastLatency = now, n, latency
}
}
func generateQuery(typ, index, field string, info *pilosa.FieldInfo, identifiers *pilosa.RowIdentifiers, opt queryOptions) (string, error) {
switch typ {
case "row":
return generateRowQuery(index, field, identifiers), nil
case "row-bsi":
return generateRowBSIQuery(index, field), nil
case "row-range":
return generateRowRangeQuery(index, field, identifiers, opt.from, opt.to), nil
case "count":
return generateCountQuery(index, field, identifiers), nil
case "intersect":
return generateIntersectQuery(index, field, identifiers), nil
case "union":
return generateUnionQuery(index, field, identifiers), nil
case "difference":
return generateDifferenceQuery(index, field, identifiers), nil
case "xor":
return generateXorQuery(index, field, identifiers), nil
case "groupby":
return generateGroupByQuery(index, field), nil
case "topk":
return generateTopKQuery(index, field, opt.from, opt.to), nil
default:
return "", fmt.Errorf("invalid query type: %q", typ)
}
}
func generateRowQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
if len(identifiers.Rows) > 0 {
return fmt.Sprintf("Row(%s=%d)", field, chooseRowID(identifiers))
}
return fmt.Sprintf("Row(%s=%q)", field, chooseRowKey(identifiers))
}
func generateRowBSIQuery(index, field string) string {
return fmt.Sprintf("Row(%s > 0)", field)
}
func generateRowRangeQuery(index, field string, identifiers *pilosa.RowIdentifiers, from, to time.Time) string {
if len(identifiers.Rows) > 0 {
return fmt.Sprintf("Row(%s=%d, from='%s', to='%s')", field, chooseRowID(identifiers), from.Format("2006-01-02T15:04"), to.Format("2006-01-02T15:04"))
}
return fmt.Sprintf("Row(%s=%q, from='%s', to='%s')", field, chooseRowKey(identifiers), from.Format("2006-01-02T15:04"), to.Format("2006-01-02T15:04"))
}
func generateRowQueries(index, field string, identifiers *pilosa.RowIdentifiers) string {
a := make([]string, rand.Intn(9)+1)
for i := range a {
a[i] = generateRowQuery(index, field, identifiers)
}
return strings.Join(a, ", ")
}
func generateCountQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
return fmt.Sprintf("Count(%s)", generateRowQuery(index, field, identifiers))
}
func generateIntersectQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
return fmt.Sprintf("Intersect(%s)", generateRowQueries(index, field, identifiers))
}
func generateUnionQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
return fmt.Sprintf("Union(%s)", generateRowQueries(index, field, identifiers))
}
func generateDifferenceQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
return fmt.Sprintf("Difference(%s)", generateRowQueries(index, field, identifiers))
}
func generateXorQuery(index, field string, identifiers *pilosa.RowIdentifiers) string {
return fmt.Sprintf("Xor(%s)", generateRowQueries(index, field, identifiers))
}
func generateGroupByQuery(index, field string) string {
return fmt.Sprintf("GroupBy(Rows(%s))", field)
}
func generateTopKQuery(index, field string, from, to time.Time) string {
return fmt.Sprintf("TopK(%s, from='%s', to='%s')", field, from.Format("2006-01-02T15:04"), to.Format("2006-01-02T15:04"))
}
// loadFields returns a mapping of index/field names to field info & identifiers.
func loadFields(ctx context.Context, client *pilosa.InternalClient) (map[fieldKey]*fieldInfo, error) {
indexes, err := client.Schema(ctx)
if err != nil {
return nil, err
}
m := make(map[fieldKey]*fieldInfo)
for _, ii := range indexes {
for _, f := range ii.Fields {
log.Printf("field: index=%s name=%s type=%s", ii.Name, f.Name, f.Options.Type)
switch f.Options.Type {
case "set", "mutex", "time":
identifiers, err := fetchFieldIDs(ctx, client, ii.Name, f.Name)
if err != nil {
return nil, fmt.Errorf("fetch fields: %w", err)
} else if len(identifiers.Rows) > 0 || len(identifiers.Keys) > 0 {
m[fieldKey{ii.Name, f.Name}] = &fieldInfo{f, identifiers}
}
case "int":
m[fieldKey{ii.Name, f.Name}] = &fieldInfo{info: f}
}
}
}
return m, nil
}
// fetchFieldIDs returns a list of field IDs or keys.
func fetchFieldIDs(ctx context.Context, client *pilosa.InternalClient, indexName, fieldName string) (*pilosa.RowIdentifiers, error) {
resp, err := client.Query(ctx, indexName, &pilosa.QueryRequest{Index: indexName, Query: `Rows(` + fieldName + `)`})
if err != nil {
return nil, err
}
switch result := resp.Results[0].(type) {
case *pilosa.RowIdentifiers:
return result, nil
case pilosa.RowIdentifiers:
return &result, nil
default:
return nil, fmt.Errorf("unexpected result type: %T", result)
}
}
func chooseRowID(identifiers *pilosa.RowIdentifiers) uint64 {
return identifiers.Rows[rand.Intn(len(identifiers.Rows))]
}
func chooseRowKey(identifiers *pilosa.RowIdentifiers) string {
return identifiers.Keys[rand.Intn(len(identifiers.Keys))]
}
type fieldKey struct {
index string
field string
}
type fieldInfo struct {
info *pilosa.FieldInfo
identifiers *pilosa.RowIdentifiers
}
func compareFieldKeys(x, y fieldKey) int {
if cmp := strings.Compare(x.index, y.index); cmp != 0 {
return cmp
}
return strings.Compare(x.field, y.field)
}
type queryOptions struct {
from, to time.Time
}

View file

@ -1,33 +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.
/*
This is the entrypoint for the Pilosa binary.
*/
package main
import (
"fmt"
"os"
"github.com/pilosa/pilosa/v2/cmd"
)
func main() {
rootCmd := cmd.NewRootCommand(os.Stdin, os.Stdout, os.Stderr)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

596
cmd/random-query/main.go Normal file
View file

@ -0,0 +1,596 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"math"
"math/rand"
nethttp "net/http"
"os"
"strconv"
"strings"
"time"
"github.com/gogo/protobuf/proto"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/client"
fb_proto "github.com/molecula/featurebase/v3/encoding/proto"
"github.com/molecula/featurebase/v3/pb"
"github.com/molecula/featurebase/v3/pql"
"github.com/molecula/featurebase/v3/vprint"
"github.com/pkg/errors"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
// RandomQueryConfig
type RandomQueryConfig struct {
HostPort string
TreeDepth int
QueryCount int
Verbose bool
GenerateOnly bool
NumRuns int
TimeFromArg string
TimeToArg string
TimeFrom time.Time
TimeTo time.Time
TimeRange int64
Index string
QPM int
Seed int
SrcFile string
Duration time.Duration
Target vegeta.Target
IndexMap map[string]*Features
API *pilosa.API
Info []*pilosa.IndexInfo
BitmapFunc []string
Rnd *rand.Rand
}
type API interface {
// InternalClient
Schema(ctx context.Context) ([]*pilosa.IndexInfo, error)
Query(ctx context.Context, index string, queryRequest *pilosa.QueryRequest) (*pilosa.QueryResponse, error)
// API for contrast; just a little different:
//Schema(ctx context.Context) []*IndexInfo
//Query(ctx context.Context, req *pilosa.QueryRequest) (pilosa.QueryResponse, error)
}
// have to wrap because the ugly little differences between InternalClient and API
type wrapper struct {
api *pilosa.API
}
func (w *wrapper) Schema(ctx context.Context) ([]*pilosa.IndexInfo, error) {
return w.api.Schema(ctx, false)
}
func (w *wrapper) Query(ctx context.Context, index string, queryRequest *pilosa.QueryRequest) (*pilosa.QueryResponse, error) {
r, err := w.api.Query(ctx, queryRequest)
return &r, err
}
func wrapApiToInternalClient(api *pilosa.API) *wrapper {
return &wrapper{api: api}
}
// These times are copied from the "kitchen sink" data generator to serve as defaults.
var defaultEndTime = time.Date(2020, time.May, 4, 12, 2, 28, 0, time.UTC)
var defaultStartTime = defaultEndTime.Add(-5 * 365 * 24 * time.Hour)
// call DefineFlags before myflags.Parse()
func (cfg *RandomQueryConfig) DefineFlags(fs *flag.FlagSet) {
fs.StringVar(&cfg.HostPort, "hostport", "localhost:10101", "host:port of pilosa to run random queries on.")
fs.IntVar(&cfg.TreeDepth, "max-nesting-depth", 1, "depth of random queries to generate.")
fs.IntVar(&cfg.QueryCount, "queries-per-request", 1, "number of random queries to generate")
fs.IntVar(&cfg.NumRuns, "number-reports", 1, "number of reports generate ")
fs.IntVar(&cfg.Seed, "seed", int(time.Now().Unix()), "RNG seed, defaults to current time")
fs.DurationVar(&cfg.Duration, "metrics-period", 10*time.Second, "size of time window on metrics reporting, default 10s")
fs.StringVar(&cfg.Index, "index", "i", "index to run queries against")
fs.IntVar(&cfg.QPM, "qpm", 10, "number of current requests per minute to simulate, default 10")
fs.BoolVar(&cfg.Verbose, "v", false, "show queries as they are generated")
fs.BoolVar(&cfg.GenerateOnly, "generate-only", false, "only generate do not run package")
fs.StringVar(&cfg.TimeFromArg, "time.from", defaultStartTime.Format(time.RFC3339), "starting time for time fields (format: 2006-01-02T15:04:05Z07:00)")
fs.StringVar(&cfg.TimeToArg, "time.to", defaultEndTime.Format(time.RFC3339), "starting time for time fields (format: 2006-01-02T15:04:05Z07:00)")
fs.StringVar(&cfg.SrcFile, "query-file", "", "use pql contained in this file for query batch instead of generating")
}
// call c.ValidateConfig() after myflags.Parse()
func (c *RandomQueryConfig) ValidateConfig() error {
if c.TreeDepth < 1 {
return fmt.Errorf("-d depth must be 1 or greater; saw %v", c.TreeDepth)
}
if c.QueryCount < 0 {
return fmt.Errorf("-n count must be 0 or greater; saw %v", c.QueryCount)
}
var err error
c.TimeFrom, err = time.Parse(time.RFC3339, c.TimeFromArg)
if err != nil {
return fmt.Errorf("-time.from value couldn't be parsed: %w", err)
}
c.TimeTo, err = time.Parse(time.RFC3339, c.TimeToArg)
if err != nil {
return fmt.Errorf("-time.to value couldn't be parsed: %w", err)
}
c.TimeRange = int64(c.TimeTo.Sub(c.TimeFrom).Hours())
if c.TimeRange < 1 {
return fmt.Errorf("time.to (%s) should be at least one hour after time.from (%s)",
c.TimeToArg, c.TimeFromArg)
}
if c.QPM <= 0 {
return fmt.Errorf("-qpm must be positive")
}
return nil
}
var ProgramName = "random-query"
func main() {
myflags := flag.NewFlagSet(ProgramName, flag.ExitOnError)
cfg := NewRandomQueryConfig()
cfg.DefineFlags(myflags)
err := myflags.Parse(os.Args[1:])
if err != nil {
fmt.Fprintf(os.Stderr, "\n%v\n", err.Error())
os.Exit(1)
}
err = cfg.ValidateConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "%s error: %s\n", ProgramName, err)
os.Exit(1)
}
err = cfg.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
func (cfg *RandomQueryConfig) Run() (err error) {
remoteClient := nethttp.DefaultClient
cli, err := pilosa.NewInternalClient(cfg.HostPort, remoteClient, pilosa.WithSerializer(fb_proto.Serializer{}))
if err != nil {
return err
}
err = cfg.Setup(cli)
if err != nil {
return err
}
rate := vegeta.Rate{Freq: cfg.QPM, Per: time.Minute}
duration := cfg.Duration
targeter := vegeta.NewStaticTargeter(cfg.Target)
attacker := vegeta.NewAttacker()
for i := 0; i < cfg.NumRuns; i++ {
vprint.VV("================")
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration, "Big Bang!") {
metrics.Add(res)
}
metrics.Close()
rpt := vegeta.NewTextReporter(&metrics)
rpt(os.Stdout)
}
return nil
}
type Features struct {
Slc []IndexFieldRow
Ranges []IndexFieldRange
Distinctables []IndexFieldRange
Stores []IndexFieldRow
SlcWeight int
RangeWeight int
}
// Pick either a feature entry or a random query on a range, weighted
// by number of features and approximate weight of ranges
func (f *Features) RandomQuery(cfg *RandomQueryConfig) *Tree {
r := cfg.Rnd.Intn(f.SlcWeight + f.RangeWeight)
if r < f.SlcWeight {
return f.Slc[r].Query(cfg)
}
r = cfg.Rnd.Intn(len(f.Ranges))
return f.Ranges[r].Query(cfg)
}
func NewRandomQueryConfig() *RandomQueryConfig {
return &RandomQueryConfig{
IndexMap: make(map[string]*Features),
}
}
type IndexFieldRow struct {
Index string
Field string
RowID uint64
RowKey string
IsRowKey bool
HasTime bool
IsInt bool
}
func (fea *IndexFieldRow) Query(cfg *RandomQueryConfig) *Tree {
fromTo := ""
// 5% of queries on a time field will use the standard view
// anyway.
if fea.HasTime && cfg.Rnd.Int63n(20) != 0 {
startHours := (cfg.Rnd.Int63n(cfg.TimeRange - 1))
endHours := cfg.Rnd.Int63n(cfg.TimeRange-startHours) + 1 + startHours
startTime := cfg.TimeFrom.Add(time.Duration(startHours) * time.Hour)
endTime := cfg.TimeFrom.Add(time.Duration(endHours) * time.Hour)
fromTo = fmt.Sprintf(", from=%s, to=%s",
startTime.Format(pilosaTimeFmt),
endTime.Format(pilosaTimeFmt))
}
if fea.IsRowKey {
return &Tree{S: fmt.Sprintf(`Row(%v="%v"%s)`, fea.Field, fea.RowKey, fromTo)}
}
return &Tree{S: fmt.Sprintf("Row(%v=%v%s)", fea.Field, fea.RowID, fromTo)}
}
type IndexFieldRange struct {
Index string
Field string
Min, Max, Scale int64
ScaleDiv float64
Range uint64
}
// We want to pick one of (1) a single-operation filter, (2) a
// between-filter of some kind.
// So, that's one of <=, >=, ==, !=, >, <, or
// one of [<, <], [<, <=], [<=, <=], [<=, <].
var binaryOps = []string{
"<=", ">=", "==", "!=", "<", ">",
}
func (i *IndexFieldRange) Query(cfg *RandomQueryConfig) *Tree {
r := cfg.Rnd.Int63n(10)
// this is unevenly weighted, but there's no Uint64N, and
// Int63n can't represent the whole range.
v1 := cfg.Rnd.Uint64() % i.Range
v2 := cfg.Rnd.Uint64() % i.Range
if v1 > v2 {
v1, v2 = v2, v1
}
v1 = v1 + uint64(i.Min)
v2 = v2 + uint64(i.Min)
var v1s, v2s string
if i.Scale != 0 {
v1s = fmt.Sprintf("%.*f", i.Scale, float64(int64(v1))/i.ScaleDiv)
v2s = fmt.Sprintf("%.*f", i.Scale, float64(int64(v2))/i.ScaleDiv)
} else {
v1s = strconv.FormatInt(int64(v1), 10)
v2s = strconv.FormatInt(int64(v2), 10)
}
if r < 4 {
lte := "<="
op1 := lte[:1+(r&1)]
op2 := lte[:1+((r>>1)&1)]
return &Tree{S: fmt.Sprintf("Row(%s %s %s %s %s)",
v1s, op1, i.Field, op2, v2s)}
} else {
if cfg.Rnd.Int63n(2) == 1 {
v1s = v2s
}
return &Tree{S: fmt.Sprintf("Row(%s %s %s)", i.Field, binaryOps[r-4], v1s)}
}
}
// Run a RandomQuery takes a list of RowIDFeatures and ColumnKeyObjects
// and spits back a PQL query
//
func (cfg *RandomQueryConfig) Setup(api API) (err error) {
if cfg.SrcFile != "" {
return cfg.buildPayload()
}
ctx := context.Background()
cfg.Info, err = api.Schema(ctx)
if err != nil {
return err
}
foundIntField := false
any := false
for i, ii := range cfg.Info {
if ii.Name == cfg.Index {
any = true
_ = i
for k, fld := range ii.Fields {
_ = k
switch fld.Options.Type {
case "set", "mutex", "time":
pql := fmt.Sprintf("Rows(%v)", fld.Name)
res, err := api.Query(ctx, ii.Name, &pilosa.QueryRequest{Index: ii.Name, Query: pql})
vprint.PanicOn(err)
switch x := res.Results[0].(type) {
case *pilosa.RowIdentifiers:
cfg.AddResponse(ii.Name, fld.Name, x, fld.Options.Type == "time", fld.Options.Type == "set")
case pilosa.RowIdentifiers:
cfg.AddResponse(ii.Name, fld.Name, &x, fld.Options.Type == "time", fld.Options.Type == "set")
}
case "int":
foundIntField = true
fallthrough
case "decimal":
cfg.AddIntField(ii.Name, fld.Name, fld.Options.Min, fld.Options.Max, fld.Options.Scale, fld.Options.Type == "decimal")
default:
vprint.AlwaysPrintf("ignoring field %q: unhandled type %q\n", fld.Name, fld.Options.Type)
}
}
}
}
if !any {
return errors.New(fmt.Sprintf("index %v not found", cfg.Index))
}
cfg.BitmapFunc = []string{"Union", "Intersect", "Xor", "Not", "Difference"}
if foundIntField {
cfg.BitmapFunc = append(cfg.BitmapFunc, "Distinct")
}
cfg.Rnd = rand.New(rand.NewSource(int64(cfg.Seed)))
return cfg.buildPayload()
}
func (cfg *RandomQueryConfig) buildPayload() error {
var request strings.Builder
if cfg.SrcFile != "" {
b, err := ioutil.ReadFile(cfg.SrcFile) // just pass the file name
if err != nil {
return err
}
request.WriteString(string(b))
} else {
for i := 0; i < cfg.QueryCount; i++ {
pql, err := cfg.GenQuery(cfg.Index)
if err != nil {
return err
}
request.WriteString(pql)
}
}
//TODO (twg) tls support
path := fmt.Sprintf("http://%s/index/%s/query", cfg.HostPort, cfg.Index)
header := nethttp.Header{
"Content-Type": []string{"application/x-protobuf"},
"Accept": []string{"application/x-protobuf"},
"PQL-Version": []string{client.PQLVersion},
}
req := &pb.QueryRequest{
Query: request.String(),
}
vprint.VV("%v", request.String())
if cfg.GenerateOnly {
// just output the PQL and exit
os.Exit(0)
}
payload, err := proto.Marshal(req)
if err != nil {
return errors.Wrap(err, "marshaling request to protobuf")
}
cfg.Target = vegeta.Target{
Method: "POST",
URL: path,
Body: payload,
Header: header,
}
return nil
}
func (cfg *RandomQueryConfig) AddResponse(index, field string, x *pilosa.RowIdentifiers, hasTime bool, isSet bool) {
storeID := uint64(0)
for _, rowID := range x.Rows {
cfg.AddFeature(index, field, rowID, "", false, hasTime)
storeID = rowID
}
storeKey := ""
for _, rowKey := range x.Keys {
cfg.AddFeature(index, field, 0, rowKey, true, hasTime)
storeKey = rowKey
}
idx := cfg.IndexMap[index]
if isSet {
if storeID > 0 {
idx.Stores = append(idx.Stores, IndexFieldRow{
Index: index,
Field: field,
RowID: storeID + 1,
})
}
if storeKey != "" {
idx.Stores = append(idx.Stores, IndexFieldRow{
Index: index,
Field: field,
RowKey: storeKey + "_1",
IsRowKey: true,
})
}
}
}
const maxEffectiveRange = 1000000
func (cfg *RandomQueryConfig) AddIntField(index, field string, min, max pql.Decimal, scale int64, decimal bool) {
f, ok := cfg.IndexMap[index]
if !ok {
f = &Features{}
cfg.IndexMap[index] = f
}
effectiveRange := uint64(max.Value) - uint64(min.Value) + 1
// if you have INT64_MAX and INT64_MIN, effectiveRange is 1<<64, which
// wraps to 0. Anything closer together will be fine. We accept the loss
// of accuracy in the range from not representing quite the full value
// in that edge case.
if effectiveRange == 0 {
effectiveRange--
}
// we assume that the Value of the field is already scaled, I guess?
newRange := IndexFieldRange{
Index: index,
Field: field,
Min: min.Value,
Max: max.Value,
Scale: scale,
ScaleDiv: math.Pow(10, float64(scale)),
Range: effectiveRange,
}
f.Ranges = append(f.Ranges, newRange)
if !decimal {
f.Distinctables = append(f.Distinctables, newRange)
}
// We want to add more values for larger int fields, but the
// default KitchenSink field has a range of 1<<64 which would make
// it completely dominate weights, so...
if effectiveRange > maxEffectiveRange {
effectiveRange = maxEffectiveRange
}
f.RangeWeight += int(effectiveRange)
}
func (cfg *RandomQueryConfig) GenQuery(index string) (pql string, err error) {
tree := cfg.GenTree(index, cfg.TreeDepth)
pql = tree.ToPQL()
dice := cfg.Rnd.Intn(9)
if dice == 3 { // 1 in 9 of getting a store
idx := cfg.IndexMap[index]
if len(idx.Stores) > 0 {
i := cfg.Rnd.Intn(len(idx.Stores))
fr := idx.Stores[i]
var key string
if fr.IsRowKey {
key = fmt.Sprintf(`%v="%v"`, fr.Field, fr.RowKey)
c := strings.LastIndex(fr.RowKey, "_")
n, err := strconv.Atoi(fr.RowKey[c+1:])
vprint.PanicOn(err)
n += 1
fr.RowKey = fmt.Sprintf("%v%v", fr.RowKey[:c+1], n)
} else {
key = fmt.Sprintf("%v=%v", fr.Field, fr.RowID)
fr.RowID = fr.RowID + 1
}
idx.Stores[i] = fr
pql = fmt.Sprintf("Store(%v,%v)Count(Row(%v))", pql, key, key)
return
}
}
pql = fmt.Sprintf("Count(%v)", pql)
return
}
type Tree struct {
Chd []*Tree
S string
Args []string // Extra args to pass after children, such as a field for Distinct.
}
func (tr *Tree) StringIndent(ind int) (s string) {
spc := strings.Repeat(" ", ind)
spc1 := strings.Repeat(" ", ind+1)
var chds []string
leaf := true
if len(tr.Chd) == 0 {
// leaf
} else {
leaf = false
for _, chd := range tr.Chd {
chds = append(chds, chd.StringIndent(ind+1))
}
}
if leaf {
s += fmt.Sprintf("%v %v\n", spc1, tr.S)
} else {
for i, c := range chds {
if i == 0 {
s += fmt.Sprintf("%v %v\n%v", spc, tr.S, c)
} else {
s += fmt.Sprintf("%v", c)
}
}
}
return
}
const pilosaTimeFmt = "2006-01-02T15:04"
func (cfg *RandomQueryConfig) GenTree(index string, depth int) (tr *Tree) {
features := cfg.IndexMap[index]
if depth == 0 {
return features.RandomQuery(cfg)
}
r := cfg.Rnd.Intn(len(cfg.BitmapFunc))
f := cfg.BitmapFunc[r]
tr = &Tree{S: f}
numChild := 2
switch f {
case "Union", "Intersect", "Xor":
numChild = cfg.Rnd.Intn(8) + 2
case "Not":
numChild = 1
case "Difference":
numChild = 2
case "Distinct":
numChild = 1
r = cfg.Rnd.Intn(len(features.Distinctables))
tr.Args = append(tr.Args, fmt.Sprintf("field=%s", features.Distinctables[r].Field))
}
for i := 0; i < numChild; i++ {
tr.Chd = append(tr.Chd, cfg.GenTree(index, depth-1))
}
return
}
func (tr *Tree) ToPQL() (s string) {
if len(tr.Chd) == 0 {
// leaf
return tr.S
}
var chds []string
for _, c := range tr.Chd {
chds = append(chds, c.ToPQL())
}
// If we had no extra args, this does nothing.
chds = append(chds, tr.Args...)
all := strings.Join(chds, ", ")
return fmt.Sprintf("%v(%v)", tr.S, all)
}
func (cfg *RandomQueryConfig) AddFeature(index, field string, rowID uint64, rowKey string, isRowKey bool, hasTime bool) {
f, ok := cfg.IndexMap[index]
if !ok {
f = &Features{}
cfg.IndexMap[index] = f
}
f.Slc = append(f.Slc, IndexFieldRow{
Index: index,
Field: field,
RowID: rowID,
RowKey: rowKey,
IsRowKey: isRowKey,
HasTime: hasTime,
})
f.SlcWeight++
}

View file

@ -0,0 +1,152 @@
// Copyright 2021 Molecula Corp. All rights reserved.
package main
import (
"context"
"math/rand"
"strconv"
"testing"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/boltdb"
"github.com/molecula/featurebase/v3/server"
"github.com/molecula/featurebase/v3/test"
. "github.com/molecula/featurebase/v3/vprint" // nolint:staticcheck
)
func Test_RandomQuery(t *testing.T) {
cfg := NewRandomQueryConfig()
nNodes := 1
nReplicas := 1
name := t.Name()
var nodeid []string
for i := 0; i < nNodes; i++ {
// work around a bug in the test.MustRunCluster that corrupts
// the .topology file if we only join name with one "_" underscore.
nodeid = append(nodeid, name+"__"+strconv.Itoa(i))
}
c := test.MustRunCluster(t, nNodes,
[]server.CommandOption{
server.OptCommandServerOptions(
pilosa.OptServerNodeID(nodeid[0]),
pilosa.OptServerOpenTranslateStore(boltdb.OpenTranslateStore),
pilosa.OptServerOpenTranslateReader(pilosa.GetOpenTranslateReaderFunc(nil)),
pilosa.OptServerReplicaN(nReplicas),
)},
)
defer c.Close()
var nodes []*test.Command
var dirs []string
for i := 0; i < nNodes; i++ {
nd := c.GetNode(i)
nodes = append(nodes, nd)
dirs = append(dirs, nd.Server.Holder().Path())
}
_ = dirs
ctx := context.Background()
indexes := []string{"rick"}
fieldName := []string{"f"}
idx := make([]*pilosa.Index, len(indexes))
field := make([]*pilosa.Field, len(indexes))
var err error
for i := range indexes {
idx[i], err = nodes[0].API.CreateIndex(ctx, indexes[i], pilosa.IndexOptions{Keys: true, TrackExistence: true})
if err != nil {
t.Fatalf("creating index: %v", err)
}
if idx[i].CreatedAt() == 0 {
t.Fatal("index createdAt is empty")
}
field[i], err = nodes[0].API.CreateField(ctx, indexes[i], fieldName[i], pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, 100))
if err != nil {
t.Fatalf("creating field: %v", err)
}
if field[i].CreatedAt() == 0 {
t.Fatal("field createdAt is empty")
}
}
timestamp := int64(0)
for i := range indexes {
// Generate some keyed records.
rowIDs := []uint64{}
timestamps := []int64{}
N := 10
for j := 1; j <= N; j++ {
rowIDs = append(rowIDs, uint64(j))
timestamps = append(timestamps, timestamp)
}
var colKeys []string
switch i {
case 0:
// Keys are sharded so ordering is not guaranteed.
colKeys = []string{"col10", "col8", "col9", "col6", "col7", "col4", "col5", "col2", "col3", "col1"}
colKeys = colKeys[:N]
case 1:
colKeys = []string{"col11", "col12"}
N = len(colKeys)
rowIDs = rowIDs[:N]
timestamps = timestamps[:N]
}
// Import data with keys to the primary and verify that it gets
// translated and forwarded to the owner of shard 0 (node1; because of offsetModHasher)
req := &pilosa.ImportRequest{
Index: indexes[i],
IndexCreatedAt: idx[i].CreatedAt(),
Field: fieldName[i],
FieldCreatedAt: field[i].CreatedAt(),
// even though this says Shard: 0, that won't matter. The column keys
// get hashed and that decides the actual shard.
Shard: 0,
RowIDs: rowIDs,
ColumnKeys: colKeys,
Timestamps: timestamps,
}
//vv("rowIDs = '%#v'", rowIDs)
//vv("colKeys = '%#v'", colKeys)
qcx := nodes[0].API.Txf().NewQcx()
if err := nodes[0].API.Import(ctx, qcx, req); err != nil {
t.Fatal(err)
}
PanicOn(qcx.Finish())
//qcx.Reset()
}
// end of setup.
cfg.Index = indexes[0]
PanicOn(cfg.Setup(wrapApiToInternalClient(nodes[0].API)))
for j := 0; j < 4; j++ {
index := indexes[rand.Intn(len(indexes))]
pql, err := cfg.GenQuery(index)
PanicOn(err)
//vv("pql = '%v'", pql)
// Query node0.
res, err := nodes[0].API.Query(ctx, &pilosa.QueryRequest{Index: index, Query: pql})
if err != nil {
t.Fatal(err)
}
_ = res
//vv("success on pql = '%v'; res='%v'", pql, res.Results[0])
}
}

Some files were not shown because too many files have changed in this diff Show more