profile
viewpoint
Nathan Taylor dijkstracula Edmonton, AB, Canada http://nathan.dijkstracula.net eight megs and constantly rocking

dijkstracula/Asciimatic 16

Edge detection-based ASCII art generator

dijkstracula/QConNYC2016 4

Materials for my QCon NYC 2016 talk: "Beyond Breakpoints: A Tour Of Dynamic Analysis"

dijkstracula/Advent-Of-Code-2017 3

advent of code 2017 solutions in standard ml

dijkstracula/Bandwortersplitter 1

Compound German word splitter

dijkstracula/recipes 1

things 2 eat

dijkstracula/Blitz 0

German flash card generator

dijkstracula/clojure-lab 0

Clojure workshop

dijkstracula/cmpt220f2020lab4 0

Sample repository for CMPT 220 Lab 4, Winter 2020

dijkstracula/commute 0

A commute planner.

pull request commentstellentus/go-plc

tag parser: trim "Program:" prefix

The PR is much less elegant now. 😢 😆

But I figured that would be the way to solve it.

dijkstracula

comment created time in an hour

delete branch stellentus/go-plc

delete branch : nathan/tag_parser_trim_prefix

delete time in an hour

push eventstellentus/go-plc

Nathan Taylor

commit sha 30c06641bfe9bd3afbef38436a74b6448916bb71

tag parser: trim "Program:" prefix Technically, the colon in "Program:" causes the tag parser to fail since it's an invalid character. Special-case the parser to drop this prefix if it's present.

view details

push time in an hour

PR merged stellentus/go-plc

Reviewers
tag parser: trim "Program:" prefix

Technically, the colon in "Program:" causes the tag parser to fail since it's an invalid character. Special-case the parser to drop this prefix if it's present.

+19 -1

2 comments

2 changed files

dijkstracula

pr closed time in an hour

delete branch stellentus/go-plc

delete branch : array-splitter

delete time in an hour

push eventstellentus/go-plc

James Bell

commit sha 285619667e7926e869e052234ff5d7fe51957793

Add arrays to Splitter.ReadTag

view details

James Bell

commit sha 414345d51d05627eeea00d8c68d5430e1b057451

Add arrays to Splitter.WriteTag

view details

James Bell

commit sha e1ca59ac301f3c9b65d6199f87a6891c83c93f5c

Split common code into a function

view details

James Bell

commit sha 7dbc06a1f15c77d2d7fa5d63e65a3f942db45ce3

Stop prepending empty struct prefix

view details

James Bell

commit sha 149b177bd14eef9dddd73457e8d96b30c3f06a7c

Simplify error handling

view details

James Bell

commit sha c80b17c951fa5bee498ed00379269fb156e84fc7

Merge branch 'array-splitter' Close #22

view details

push time in an hour

PR closed stellentus/go-plc

Array splitter

This does 2 things:

  • Add support for arrays
  • Add support for top-level structs (i.e. with a tag name of "")
+177 -29

0 comment

2 changed files

stellentus

pr closed time in an hour

push eventstellentus/go-plc

James Bell

commit sha df6323ace7400ef3002983ec70e58b1b08d4401b

Simplify error handling

view details

push time in an hour

Pull request review commentstellentus/go-plc

Array splitter

 func (r SplitReader) ReadTag(name string, value interface{}) error { 	return err } +func (r SplitReader) readValue(name string, val reflect.Value) error {+	if !val.CanAddr() {+		return fmt.Errorf("Cannot address %s", name)+	}++	valPointer := val.Addr().Interface()+	if val.Kind() == reflect.Ptr {+		// Since val actually is a pointer, we want its value instead.+		if val.IsNil() {+			// It's currently a nil pointer, so we need to allocate and set the value+			newVal := reflect.New(val.Type().Elem())

Immediately after I use reflect, I forget how it works. 😆

Short answer: approximately yes.

Medium answer: in this case, val.Type() is *someType, so we need val.Type.Elem() to get someType, and that's what we allocate.

Long answer:

The point of this code is to allow a user to have a pointer-to-value in their struct and we'll fill that. Otherwise they'd have to pre-allocate all of their pointers before calling this code, which is just irritating.

The input to readValue is a struct field. (Note it's the reflect.Value for the field, not a pointer to the field). If it turns out that field is a pointer and it's nil, then I get the reflect.Type of the thing we want to point to, and reflect.New allocates a new one. We then set the struct's field pointer to use that value, which gets filled in a normal call to ReadTag.

stellentus

comment created time in an hour

Pull request review commentstellentus/go-plc

Array splitter

 func (sw SplitWriter) WriteTag(name string, value interface{}) error { 			if !ok { 				continue // Can't touch that 			}-			fieldName = name + "." + fieldName // add prefix+			if name != "" {

This came up because I needed it (and it works).

Imagine I want to read these top-level tags:

MY_TAG
ANOTHER_TAG

I define a struct: type struct AllTags {MY_TAG, ANOTHER_TAG float32}

Then I read it: device.ReadTag("", &allTags)

...I think it's ok if the Locker doesn't handle this case because I think locking will occur below the Splitter.

stellentus

comment created time in 2 hours

Pull request review commentstellentus/go-plc

Array splitter

 func (r SplitReader) ReadTag(name string, value interface{}) error { 			if !ok { 				continue // Can't touch that 			}-			fieldName = name + "." + fieldName // add prefix+			if name != "" {+				fieldName = name + "." + fieldName // add prefix+			} 			field := str.Field(i)-			if !field.CanAddr() {-				err = fmt.Errorf("Cannot address %s", fieldName)+			err = r.readValue(fieldName, field)

I'm inconsistent about using it.

But in this case I think there's good reason to avoid it (maybe?).

That idiom is usually used when the returned variable is only locally scoped (e.g. when the error is immediately returned, or a value is used in the block). So the idiom is usually :=.

In this case the err is used later, so while the idiom would still work, I think it might deceive the reader. The err was used later because at one point I had some code that executed after the switch. (Or at least intended to move in that direction.)

... however, now that the code is effectively break; return err in those cases, I think the idiom would be more readable here. So good point: I'll refactor this a bit to return instead of break, using the idiom.

stellentus

comment created time in 2 hours

startedeliddell1/RollJam

started time in 5 hours

startedolegv142/CC1101

started time in 5 hours

startedgrspy/rcswitch-cc1101

started time in 5 hours

startedn8ohu/CC1101-FSK

started time in 5 hours

issue closedstellentus/go-plc

Return named error types from ReadTag and WriteTag

It would be nice to be able to distinguish between errors writing to the PLC and errors in the provided tag/value. Then users know whether the error was in their request, or in the network.

closed time in 6 hours

stellentus

pull request commentstellentus/go-plc

tag parser: trim "Program:" prefix

I think one of your test cases is (slightly) wrong.

	{"Program:Field.Array[42].Member[16]", []string{"Field", "Array", "42", "Member", "16"}, ""},

I think the first returned string should be Program:Field, not just Field. I believe it would be possible for there to be a top-level tag Field as well as a program named "Field" (with a corresponding tag name Program:Field). In that situation, I believe the tag locker would have a minor bug: those two tags would share a lock. (Likely safe with a minor performance impact.)

In our use case, this is not a problem (since none of our program names overlap with a top-level tag name), so I'm fine with approving this PR for now. But it should probably be fixed, just in case.

If this is a small change you can do within the week, I'll wait for it. Otherwise, I'll go ahead and merge the PR later this week.

dijkstracula

comment created time in 6 hours

delete branch stellentus/go-plc

delete branch : nathan/tag_locker

delete time in 7 hours

push eventstellentus/go-plc

Nathan Taylor

commit sha 05474d8cff00f85df039db6975b22d932b504418

TagLocker ReadWriter impl This patch includes an implementation of a plc.ReadWriter that gates access on a downstream ReadWriter through intention locking on each of the given tag name's components. The benchmark results for this implementation follow: BenchmarkSerialTagLocking BenchmarkSerialTagLocking-12 292084 4155 ns/op BenchmarkLowConcurrencyTagLocking BenchmarkLowConcurrencyTagLocking-12 1337608 916 ns/op BenchmarkMedConcurrencyTagLocking BenchmarkMedConcurrencyTagLocking-12 1889516 657 ns/op BenchmarkHighConcurrencyTagLocking BenchmarkHighConcurrencyTagLocking-12 1850548 651 ns/op BenchmarkSerialTagLockingWithHeavyWrites BenchmarkSerialTagLockingWithHeavyWrites-12 271552 3702 ns/op BenchmarkLowConcurrencyTagLockingWithHeavyWrites BenchmarkLowConcurrencyTagLockingWithHeavyWrites-12 1304198 1064 ns/op BenchmarkMedConcurrencyTagLockingWithHeavyWrites BenchmarkMedConcurrencyTagLockingWithHeavyWrites-12 1655668 723 ns/op BenchmarkHighConcurrencyTagLockingWithHeavyWrites BenchmarkHighConcurrencyTagLockingWithHeavyWrites-12 1753326 751 ns/op PASS As expected, throughput increases when we add a degree of concurrency, but it seems to level out pretty quickly. Unsurprisingly, as well, the intention write locks seem to decrease throughput slightly as readers will be unable to grab intention read locks on interior nodes until those operations complete.

view details

push time in 7 hours

PR merged stellentus/go-plc

TagLocker ReadWriter impl
TagLocker ReadWriter impl

This patch includes an implementation of a plc.ReadWriter that
gates access on a downstream ReadWriter through intention locking
on each of the given tag name's components.

The benchmark results for this implementation follow:

BenchmarkSerialTagLocking
BenchmarkSerialTagLocking-12                                      292084              4155 ns/op
BenchmarkLowConcurrencyTagLocking
BenchmarkLowConcurrencyTagLocking-12                             1337608               916 ns/op
BenchmarkMedConcurrencyTagLocking
BenchmarkMedConcurrencyTagLocking-12                             1889516               657 ns/op
BenchmarkHighConcurrencyTagLocking
BenchmarkHighConcurrencyTagLocking-12                            1850548               651 ns/op
BenchmarkSerialTagLockingWithHeavyWrites
BenchmarkSerialTagLockingWithHeavyWrites-12                       271552              3702 ns/op
BenchmarkLowConcurrencyTagLockingWithHeavyWrites
BenchmarkLowConcurrencyTagLockingWithHeavyWrites-12              1304198              1064 ns/op
BenchmarkMedConcurrencyTagLockingWithHeavyWrites
BenchmarkMedConcurrencyTagLockingWithHeavyWrites-12              1655668               723 ns/op
BenchmarkHighConcurrencyTagLockingWithHeavyWrites
BenchmarkHighConcurrencyTagLockingWithHeavyWrites-12             1753326               751 ns/op
PASS

As expected, throughput increases when we add a degree of concurrency, but it
seems to level out pretty quickly.  Unsurprisingly, as well, the intention
write locks seem to decrease throughput slightly as readers will be unable
to grab intention read locks on interior nodes until those operations complete.
+502 -2

4 comments

5 changed files

dijkstracula

pr closed time in 7 hours

startedSuperMaZingCoder/TableIt

started time in 10 hours

startedastanin/python-tabulate

started time in 10 hours

startedjtdx-project/jtdx

started time in a day

pull request commentstellentus/go-plc

Fix tag struct prefix

Note this is just one commit on top of #21 and #22.

stellentus

comment created time in 2 days

PR opened stellentus/go-plc

Reviewers
Fix tag struct prefix

It turns out I was using a different prefix in different places (plc and plctag). Now it's a const.

+1175 -164

0 comment

8 changed files

pr created time in 2 days

delete branch stellentus/go-plc

delete branch : james/testing-get-all-tags

delete time in 2 days

create barnchstellentus/go-plc

branch : james/fix-tag-struct-prefix

created branch time in 2 days

pull request commentstellentus/go-plc

Generate a go struct from L5X tags

It turns out the real L5X had some more extra features. I've now added them and the L5X loads in its entirety.

In order to push that branch for review (on the private repo), this PR and #22 have to be merged.

stellentus

comment created time in 2 days

PR opened stellentus/go-plc

Reviewers
Array splitter

This does 2 things:

  • Add support for arrays
  • Add support for top-level structs (i.e. with a tag name of "")
+172 -18

0 comment

2 changed files

pr created time in 2 days

push eventstellentus/go-plc

James Bell

commit sha 8f45e7ed11df481b5c5caba5a633f478bc0a0367

Improve output for StringFamily

view details

James Bell

commit sha e15db07062a4ae6fa5c0ec88eef01b488c7451f3

Add support for BOOL arrays

view details

James Bell

commit sha 6b2378c86253fc67b0465c266cd6e48b09cd3e1a

Merge branch 'array-splitter' into james/testing-get-all-tags

view details

James Bell

commit sha 8b101921c929cfdd8aa67a237e392674ca94d094

Fix struct tag prefix

view details

push time in 2 days

more