Nerd Babel

Would It Hurt To Document The Device You Sent Me?

I am actually good at this computer stuff. It is what I do. So I get frustrated when I order hardware and it doesn’t work.

A month ago, I ordered a Mini-ITX board. It was cheap, and it wasn’t 17×17 cm, it was 17x19cm. Which didn’t fit in the case. The low profile CPU cooler/fan I ordered was too tall, so I needed to get a shorter unit. It just wasn’t worth the fight.

I ordered a new Mini-ITX board. This was supposed to be the right size. Not only was it the wrong size, it only had 3 SATA ports, not the 4 on the board I ordered.

That was taken care of with still another motherboard purchase. This time all was good. And amazingly, I didn’t have to wait 2 weeks for the board to get here from China.

Everything is installed, I install the PCI SFP+ NIC, it won’t power up. I don’t know if the card is bad but I replaced the card and that machine is now in production.

Switches are the next big issue. I gave up trying to find a cheap switch, I ordered a new switch, the same as the last I purchased. It should just work.

This switch is an 8 port SFP+ unit, similar to the one in the featured image. It is powered by a 12v DC wall wart.

What arrived was a plastic box with 8 RJ45 connectors. Similar switches can be found on Amazon for under $8. To make it pass the Amazon inspectors, they threw in a free USB-A to USB-C connector. That was returned and a refund was issued.

So I ordered another L3 switch. It arrived in short order. When I powered it up, the power light came on. Then the SYS light started blinking.

Read the manual. Green blinken SYS light means the unit is starting up. Figure that it might be that the unit isn’t fully configured. No problem, I connected it to the network.

Still the blinken light. I scan the network where the device is supposed to be. No response.

Well, the instructions don’t mention the “console” port on the unit (missing from the image because they used the wrong image on the Amazon listing). I ordered a generic console cable to watch the boot sequence, maybe I can spot what went wrong.

What went wrong? Nothing.

The unit is working exactly as it should. I’ve configured it, ready to go into production. The documentation is wrong about what the green blinken light means.

Frustration with hardware, yet this time it is working correctly.

Once this device is in place, every machine, but one, will have at least on 10Gbit fiber link to the main back plain network. Every machine will have a connection to the management network.

As a side effect, it means that each data closet will have at least two fibers into the closet for redundant backup links.

Oh, this also means I can consider using bonded links to get 20G bit transfer rates. That will be cool.

HTML code close up

Document Object Model

A modern website is a complex system of inter related pieces. Each of which must work correctly and communicate correctly with the other parts of the system.

As website creators, we break the design into the Frontend and the Backend. The front end is anything the end user sees, while the back end is responsible for generating content to be displayed.

The backend is further subdivided into the Model, Controller, and View. The model is our term for the database and database access. The controller is the rules for the website. The view is the creation of content to be displayed.

Consider a website that allows you to purchase an item. The “model” would describe that item. SKU, size, weight, cost, price, images, description, name, and much more. The “controller” encodes the business rules. We can only ship to people that have paid us. And the view turns all the information into content for a browser to display.

The content is delivered as HTML. We can also supply JavaScript code and Cascading Style Sheets. The HTML can have the JavaScript and CSS embedded in the HTML or the HTML can link to other resources to be included with this page.

HyperText Markup Language

The US government wanted a standardized way of creating electronic documents for printing. This was the Standard Generalized Markup Language, ISO8879.

SGML has the advantage of being very application-specific. If you are writing a book, you use one set of tags, if you are creating the Message Of The Day, you use a different set of tags.

The power of markup is that you describe what you are marking up, rather than formatting whatever it might be.

Consider and address. Bilbo Baggins, 999 Bagshot Row, Hobbiton, The Shire. As written in this sentence, it is just a row of text. You could write it that way on a letter and it would be delivered, but the postman would be unhappy at the formatting

<b>Bilbo Baggins</b><br/>
999 Bagshot row<br/>
Hobbiton, The Shire<br/>

Is the address formatted, which looks like

Bilbo Baggins
999 Bagshot row
Hobbiton, The Shire

Using DocBook, a particular version of SGML, we would write that same address something like:

<address><surname>Baggins</surname><givenname>Bilbo</givenname>
<street>99 Bagshot row</street>
<city>Hobbiton</city><state>The Shire</state>
</address>

We do not know how to display the address, but we know that it is an address. If we are provided rules on how to display addresses, we can display this address per the rules.

Structure

HTML was designed to be simpler than SGML. There are fewer tags, and the fixed meaning of the tags made it easy to write HTML by hand.

Almost every post I create is written in raw HTML. That HTML is then styled and displayed in nearly pretty ways.

HTML defined the structure of the document. The structure was of a header section, describing the page, and a body section with the actual content.

Within the content section were the different displayable content. You had headers, levels 1 through 5, you had numbered lists, unnumbed lists, and definition lists (a word with an attached definition). There were paragraphs, links, tables, and finally, there were images.

This content was rendered however the browser wanted to.

There were formatting tags for bold, italics, blinking, and not much more.

If you wanted to “layout” your webpage, you used tables and fought to get things right.

Cascading Style Sheets

CSS allowed us to provide styling to an element. The paragraph above has margins, padding, and boarders applied to it. It has colors applied for the background and for the font. All are set via a style sheet. Your browser has a default style for each element.

The problem that arises is how to attach that styling to particular elements. The answer starts with the structure of the document.

p {
  color: red;
  background-color: green;
  margin-left: 50px;
  border: 2px;
}

This uses a CSS selector, ‘p’ to locate all paragraph elements. It then sets the background to green, the font to red, moves it to the right 50px, then draws a 2px solid border around the paragraph.

This is a basic selector. Selectors get very complex.

DOM

Every element in an HTML document is loaded into the DOM. From there, we can select elements and modify the style of the element with CSS and CSS Selectors.

The simplest method is to give important elements an ID. IDs are unique for a DOM. If there is more than one element with the same ID, this will generate an error, which most people will never see. The rules tell us which element will own that identifier.

To find a particular element with a particular ID you use the ‘#’ symbol. Thus, to find the header just above, we would write “#DOM”. While the header would look like <h3 id=”DOM”>DOM</h3>.

We can add a multiuse identifier, called a class, to multiple elements at the same time. <div class=”quote”> is the code I use to create a quote. The class “quote” has a CSS group attached. This causes all the divs of class quote to be rendered as a block quote.

We then have the tag selector. We used one above with the “p” element. This allows us to select all the elements of a particular type. The selector “li” would select all the list items in the DOM. We could use this to make every line italic.

We can combine selectors to limit which elements are selected. “ul>li” would select all line items of unordered(without numbers) list, while “ol>li” would select all line items which were part of an ordered (with numbers) list.

These selectors can even allow us to move through the DOM in a structured way. We can ask for the first paragraph after a header for special treatment.

DOM Manipulation

When we load JavaScript on a web page, that JavaScript can watch for events on elements. This is done by locating an element with a selector, then watching for a particular event to take place on that element.

The JavaScript can then modify the DOM. This can be by changing the structure of the DOM, or it can be modifying the style of elements in the DOM.

A recent example of this, I added a class to some table data items (td). I did it with a class. I then found all the elements with that class and watched for a mouse click on those elements.

When the click was detected, my JavaScript ran. The JavaScript grabbed the contents of the element, stripped out formatting, then put that content into a text input box, displayed the text input box for the user to edit.

When the user completed their edit, the value they entered was formatted, the input was removed from the DOM. The formatted value was then placed back in the element.

All with a bit of good selection to make it work.

Finally, Selenium uses different types of selectors to find elements for manipulation or testing.

Very powerful stuff.

Quality Assurance and Document Control with Checklist Icons. Businessman mark off items on digital checklist, representing quality assurance and document control processes, verification and compliance

Unit testing

This is boring geek babble.

Quality Assurance is not something computer nerds are good at. It is boring, repetitive, and difficult.

That doesn’t mean it shouldn’t be done. Instead, it means that you need somebody to do QA for you. You cannot do QA on your own. You won’t see your own errors.

Consider a simple unit test. You have just created a new model (database table). You know you have created it correctly. Some of that is because you trust the infrastructure you are using, but mostly it is because it has worked in the past.

To do a proper unit test, you would need to verify that you can read and write an object of that model. That each functional manipulation does what is should, and that all possible options into the functional unit works.

In the past, I would test student programs that did simple math. For example, they would write a simple four function calculator. I’m the ass that would get their calculator to attempt to divide by zero. They had to handle that case.

The thing that happens, is that as we are developing new code, we test that code, extensively. We know what we are adding and what it should do. We don’t “retest” what we know is already tested and working.

Last Tuesday, that nearly broke me. I had tested my code, was getting ready to deploy the code. Before deploying, I was doing some testing. It wasn’t until I clicked on a link that went to a page I was not going to be testing that I discovered a major error.

I wasn’t even planning on looking at that page.

Here is another example, you have a standardized header for your website. If you check it on one page, why should you test the header on every page? It should work the same. So you don’t test it on every page. Except that there is one page that doesn’t set a context variable, so it causes errors on the page. Because you didn’t test that particular page, the error is missed.

This is where unit tests are a win. In theory, you write a test for every part.

Currently, I’m working with Selinium, This is an API that interfaces to an actual browser. This allows you to control the browser via code.

The basics are you write code to find a page element, you can then verify different aspects of the page.

I’m currently writing code to test the left column. The left-hand column is on almost every page of the website. In the past, I’ve verified the parts of that column I’ve been working on. I haven’t verified the entire column since I first created the site.

Using Selenium, I am able to run the same set of tests against the left column on every page. I can also verify that every menu item opens and closes. I can exercise the entire website.

Because it is so easy to do this, I can just run the tests every time, giving me better results.

Of course there is a learning curve. Of course it takes a different mindset to do these tests. Regardless, it is worth it.

Group Of People Writing On Sticky Notes Attached To Blackboard In Office

Project Management

Love it or hate it, project management is a thing. It has to be there. If you don’t think it is there, you are just doing it badly.

Project Managers are a different kettle of fish. Some need to be boiled alive. Others can just dance on hot rocks. And a very few can sit at the big boys’ table.

I’m coming off the end of a rush project that was big. I had to take a customized system and add tariffs to it with about 14 days from concept to deployed. More than a little to get done.

When I started programming, I had a choice of an 8080 with a 24×80 character display, or a 6502 with a 24×40 character display.

When I was introduced to JOVE, Jonathan’s Own Version of EMACS, I fell in love with it. Multiple views into the same file, the ability to copy and paste from different files or different places in the same file. And auto indentation.

Powerful stuff for the time.

My fingers worked will with vi and later vim because I played Nethack and before that, Hack. The programs had a particular key set for moving the cursor based on the key caps of a terminal type used at MIT.

The author had never seen a terminal without arrows over the J, K, H, and L keys. To give you an idea of how ingrained those are, I had to fire up vim and tell my fingers “down”, “up”, “right”, and “left” to record the keys for this sentence. My fingers know, I don’t.

Besides jove, I learned emacs. Emacs is my programming editor. It is what I use when I need to write a lot of code or text. With modern computers, it starts just as fast as jove ever did on a 68020 class CPU.

The problem we had was keeping track of what needed to be done or fixed. This might start off as a document, written with jove in troff. This could be fed to different processors to create PostScript files to be sent to our printers.

Later, some of us used LaTeX for the same thing. Your “design document” was a separate file that was “fixed” before you started coding. These documents never contained more than brief pseudocode and discussions of algorithms.

As you were coding, if you discovered something, you created a comment and marked it. The two most common marks were, XXX which meant that the code was broken in some way, but it didn’t need to be fixed now. All XXX marks had to be addressed before the code could be released.

The other mark was TODO. This was working code but needed some features or extensions added. These did not need to be fixed before release.

In general, we used grep to find all these markers in a list of files. It wasn’t difficult.

The small program I’m working with has some 250k lines of code. After 3 or 4 years of supporting this site, I would say I’ve looked at every line of code in the system.

Finding every marker in 4100 files across 1200 directories is a pain.

Enter Kanban

Kanban is a project management tool. The concept is easy enough to do with sticky notes and a white board or notes with push pins on a larger bulletin board.

Today, the normal Kanban has 4 columns to hold cards. The cards are labeled, “backlog”, “To Do”, “Doing” or “Working”, and “Done”.

When you create a card it goes into the “backlog” column. These are issues or tasks that have no resources assigned to them.

Once per week, there is a meeting of the workers and the project manager. In this meeting, the project manager evaluates the cards that are in the “Done” column. If they are truly done, then they are removed from the board and added to the QA project.

Cards that are in the working column stay in the working column. Cards that are in the working column can be moved into the backlog column if some other card blocks them.

For example, if you have a card that says, “Put new tire on left front wheel” it cannot be worked on until the card that says, “Purchase a new tire for the front left wheel.” Until the purchase card is completed, you can’t work on the installation card.

If there are any resources (workers/developers) that think they are going to need more tasks to work on, the project manager will take cards from the backlog column and move them to the To-Do column.

When a worker requires more work, they move the card from the To-Do column to the working column. When they complete the card, they move it to the Done column.

I’ve used Kanban in the past. It never really appealed to me as it didn’t feel any different from the old ways of doing things.

For this latest project, I used my Kanban board.

Instead of putting markers in the code, I opened a new issue. That issue just went into the “backlog” column. I could tag the issue as a bug or a feature. I could indicate that cards were blocked. It was faster to create the issues/cards than to make entries into the files and then try to locate them later.

Today, I’ll be looking through anything in the QA column and writing unit or web tests for them. I’ll also be doing a QA across the site, to add to the project board.

The biggest thing for me was the ability to visual see what still needed to be done.

Conclusion

Good tools make the work go faster.

Ivory Ball Phython Snake curled up in the straw.

How Many Languages Do You Speak?

In computer languages, there are very few that are structurally different.

FORTRAN is like COBOL, which is like Pascal, which is like BASIC, which is like ADA, which is like …

Forth is not like those above. Nor is APL or Lisp.

Assembly languages can be used in structured ways, just like FORTRAN, COBOL, Pascal, and many others. It requires the discipline to use if not condition jump skip_label; do stuff in condition; skip_label:. The actual programming logic stays the same.

The two computer languages I dislike the most are PHP and Python. Both because they are weakly typed.

In a strongly typed language, you declare a variable’s type before you use it. The type of the variable is immutable for its lifetime.

In other words, if you declare a variable of being of type integer and then attempt to assign a string to it, it will barf on you during compilation.

In PHP, all variables look the same, any variable can hold any type at any moment. The type can change from line to line. And the language will do implicit type casting. It is hateful.

Python has all the same characteristics I hate in PHP, with the added hateful feature of using indentation instead of begin-and markers for blocks.

I’m lucky that Python has an optional typing capability, which I use consistently. The optional part is a pain when I want to use a module that has no typing information. When that happens, I need to create my own typing stub.

But the worse part of all of this is that they get jumbled together in my head. How many entries in an array? In PHP, that is determined by the count() function, in Python it is the len() function.

In Python, the dot (.) is used to access methods and attributes of objects. In PHP, it is the concatenation symbol.

I am tired of writing Python in my PHP files and I dread switching back to Python because I know my fingers will mess things up.

Person holding a small paper

Remote Repositories for GIT

Definitions

When working with git, there are several areas we might be discussing. The most important areas are “working directory”, “staging”, “local repository”, and “remote repository”.

A repository without a working directory is called a “bare repository”.

The working directory is a location where your files live, with a reference back to the repository. It is possible to extract the files without keeping a reference to the repository.

Most working directories, and what we will assume for our discussion, have the bare repository within the .git directory (folder).

A remote repository is normally a bare repository located somewhere apart from your local working directory. This could be a different directory on the local machine, or it could be located on a remote, network connected system.

Creating a Local Version of a Remote Repository

This is what the remote repository looks like. A pretty simple version.

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"

We don’t copy it, we clone it. The implication is that what we have in the local version is the same as what is in the remote version.

git clone ssh:git@github.com/author/book.git

This creates a directory named “book”, it clones/copies the bare repository from GitHub and places it in “book/.git”. It creates a “remote” reference within “book/.git/refs/remotes” named “origin”. With “origin” it creates a copy of all the branches that are in the remote repository, in our example, just “master”

The clone command then checks out the working directory into “books”. This would be the files “chapOne.md”, “chapTwo.md”, and “chapThree.md”. It creates a file in “books/.git/refs/heads” named master with the commit hash (identifier) of “0ccd79797”.

This is a copy of refs/remotes/origin/master.

Our diagram now looks something like:

%%{ 'gitGraph': {'rotateTag': true}}%%
gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797" tag: "origin/main"

At this point, you start work on your three files over two commits, your local repository now looks like:

%%{ 'gitGraph': {'rotateTag': true}}%%
gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797" tag: "origin/main"
   commit id: "7d918ddc0"
   commit id: "f4b0d4086"

Meanwhile, your editor has fixed some typos and grammar errors and pushed those to the remote repository.

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"
   commit id: "cd6023b24"
   commit id: "ac6d2dd15"

These two look the same, but notice that the last two commits have different values/hashes. This is because they are different.

Since you are done with your edit, you attempt to send your changes back to the remote repository named “origin” via a push command. git push origin main This fails because there would be two versions of the repository if you did this, there can be only one.

To correct this, you first fetch an updated copy of repo.

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"
   branch origin/main
   checkout origin/main
   commit id: "cd6023b24"
   commit id: "ac6d2dd15"
   checkout main
   commit id: "7d918ddc0"
   commit id: "f4b0d4086"

This is done with git fetch origin This command updates only the bare repo.

We now need to combine these two branches, this is done with git merge origin/main After which our local repository looks like.

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"
   branch origin/main
   checkout origin/main
   commit id: "cd6023b24"
   commit id: "ac6d2dd15"
   checkout main
   commit id: "7d918ddc0"
   commit id: "f4b0d4086"
   merge origin/main id:"119c29222"

We then add some more to the story line and make one more commit.

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"
   branch origin/main
   checkout origin/main
   commit id: "cd6023b24"
   commit id: "ac6d2dd15" tag: "origin/main"
   checkout main
   commit id: "7d918ddc0"
   commit id: "f4b0d4086"
   merge origin/main id: "119c29222"
   commit id: "040e63c01"

We do another fetch, there is nothing to do as nothing else has been added. We then push our commits back to the remote repository. git push origin main

gitGraph
   commit id: "d6458df1e"
   commit id: "0ccd79797"
   commit id: "cd6023b24"
   commit id: "ac6d2dd15"
   commit id: "7d918ddc0"
   commit id: "f4b0d4086"
   commit id: "119c29222"
   commit id: "040e63c01"

Because I’m not the program, there might be some small ordering issues in the final commit.

The point in all of this is that all of this magic happens behind the scenes. The program can do most merges with no assistance from you. In the rare cases where there is a merge conflict, it is relatively easy to manual merge the changes.

A merge conflict happens when two commits modify the same line of code. In your version, you had “Ciliorys hat” originally. You modified it to be “Billy-Bobs hat” Your editor had changed it to “Cilory’s hat”.

Now you have two edits to the same line. Git says, “You figure it out.” and shows you the two versions of the line, in context. You can pick one version or the other, or put in an entirely different version.

You choose the third option and put “Billy-Bob’s hat”. The world is good.

Conclusion

git is powerful. This discussion barely touches on the power of git.

There is an entire process of modifying code by “forking” a repository. When you are finished with your modifications, you can contribute them back to the original repository with a “Pull Request”.

Git has multiple methods of inserting code review and other tools into the process.

It is so powerful, It can be used to create a full wiki, on the fly. The raw files are served as wiki pages.

There is a method of doing a binary subdivision to find bugs that were introduced in the past. There is a method of tracking who introduced an errant line of code.

There are tools for pulling a commit out of the middle of a branch and applying it to a different branch, without taking the rest of the modifications.

In general, there only about a dozen commands that a user needs to know to work with git.

If you would like to work with git, there are communities ready to help you, there are multiple cloud providers that will allow you to host your repo on the web.

Person holding a small paper

Source Code Control for Beginners

Update

My introduction to source code control came at University. The name of the program was “update”. It took an “update deck” which described lines to remove, by line number, and lines of code to insert.

This format allowed us to inspect the code that was actually being changed, as well as the surrounding code. Every line of code I wrote for the Systems Group that was installed went through three levels of code review and QA testing before going live in the system.

Having those change decks helped in the review process. As a side note, the author’s initials were attached as a note to the right of every line of code we modified. Easy stuff.

After a change deck was accepted, it became part of the “installed version” of the software.

One of the powerful features of working with change decks is that two (or more) people could be working on the same piece of code and unless their changes overlapped, they could be applied independently.

RCS

When I left University, I started working with the BRL CAD project. This introduced me to the RCS system.

RCS was something like “update” but not quite. And you didn’t think in terms of “change decks”. That was handled behind the scenes.

You had a directory (folder) in which you had your code. You also had hidden files that stored the RCS history of the code.

By default, files were stored read-only. You could read them, you could compile from them, but you could not modify them.

To modify a file, you needed to first check out the file. When you checked out a file, it was “locked” to you and nobody else was allowed to modify the file.

You made the changes you wanted to the checked out files, then you tested. When you were happy that your code worked, you checked in the file you had checked out.

This is great when modifying a single file, but if you are modifying more than one file to accomplish your fix or enhancement, you have to check in each file in a separate operation.

There was no linkage between the files to indicate that all the changed files needed to be processed as a gestalt.

When you were ready to make a release, you had to do some magic to mark each file as being part of that particular tag. Then, at a later time, you could check out that entire tree and work on it as if it was the day of the release.

RCS did magic behind the scenes to figure out the “delta” between the checked out code and the original. This was equivalent to the “update deck” I was used to from University Days.

To work in a collaborative methodology, you would have a single “working directory” with everybody on the team having read/write privileges to the directory. If you were working across multiple machines, each machine had to use the same shared directory via a network file system. (NFS at the time)

At one point, I was working on BRL CAD on my home machine. I did not have enough space on the drive to copy the entire RCS tree to my local drive, so I was using NFS over a 28.8k dial-up modem.

Compile times ran about 3 days. And if anybody changed one of the “big” include files, I would have to start the build over again.

If you were working on a copy of the source code, you would extract a patch file from RCS to submit back to the master RCS directory.

It felt easy at the time, but it wasn’t as easy as it seamed. We just didn’t know what we didn’t know.

CVS

CVS was the first major paradigm change in source code control for us. The basic use was the same as with RCS, but they had changed the layout.

You now had an explicit directory, CVS, which contained the history files. When you checked out files, the lock was done in the CVS directory.

In addition, you could check out the files read-only (no lock) remotely from the CVS directories and then checkout with a lock, edit on the remote system, then check in your changes.

This was a game changer. We no longer required a network file systems.

Unfortunately, we had some of the same issues as we had with RCS. The main one being that only one person could check out/lock a file at a time. With team members working nearly 24 hours per day, it was a pain when the morning dude wasn’t available at 2237 to release a lock.

SVN

SVN solved most of the known problems with CVS. It had the concept of a remote repository, it allowed multiple people to work on the same file at the same time. It had better branch and tag capabilities.

All in all, it was a vast improvement.

The two primary weaknesses were no gestalt for files and very slow check out of branches and tags away from the main trunk.

I remember using SVN. I had to use it just a couple of weeks ago. I don’t think I ever fell in love with it. It was a step-wise improvement over CSV.

git

Git is my favorite source control system. I understand that there is another SCS, but I can recall its name at this point. I’ve not used it.

Git changed the paradigm we use for changing the repository. Whereas all the previously discussed SCS’s work on a file by file basis, git works on a “commit” basis.

Even if you are working in a collaborative environment, you work on your personal repository (repo). We will get to collaborative environments shortly.

In the simplest form, you create a “working directory” which you populate with your code. That could be a book, a program, an application, or a web page. It doesn’t matter. Git doesn’t care what the files contain, only that they be text files.

Git can work with binary files, but that is not our focus.

Once you have your initial contents, you create your repo with git init. With this magic command, git creates all the required files to track the history of your project.

Let’s say you are working on a book. You have placed each chapter of the book in a separate file. One of your characters is named Cillary Hlinton. Your editor tells you that the name is just too close to a real person, and he would rather not be sued. He asks you to change the character’s name.

Under update, RCS, CVS and SVN, you would check out individual files, change the name to “Billy Boy” and then check in your changes. When you have made all the changes, you are happy.

The issue is that there Chapter One is on revision 44, Chapter Two is on revision 37, and Chapter Three is on revision 48. How do you figure out the revision from just before you made the changes?

With git, you do not check out files and lock them. Instead, all files are ready for you to modify. You just edit the files and change the name.

Now you have chapters one, two, and three that have been modified. You group them into a single commit by adding them to the staging area. git add chap1.md chap2.md chap3.md

You can do this on one git add or multiples, in one session or multiple sessions. At some point you will be satisfied with your collection of changed files.

At that point, you commit the changes. You will be required to supply a message.

Each of the following circles represents a commit.

Before Name change

After the name change

If we want to see the version before the name change, we can check out commit 4. When we do, all the files are changed back to the version before adding your name changes.

This makes it easy to find one particular point where the state of the book is one way and in the next commit, all the changes have taken place across the entire book.

The other major improvement that git brought was fast branches.

Branches

Here we see two branches added to the repository. The first “HEAD” is a special branch. It represents the commit associated with the working directory. It is manipulated implicitly instead of explicitly.

“master” is the default branch until “rrracist” was applied, so some repos now use “main” instead of “master” branch.

This ability to create branches rapidly allows us to make and destroy branches at will.

We are going to create a new branch, “editor” for our editor to work on. Meanwhile, you are continuing work on chapter four.

Editor and Master branches

And here is where git shows another of its powers, the merge. With the ‘master’ branch checked out, we merge the editor branch, fixing all the little grammar and spelling errors. git checkout master; git merge master

After Merge

With this merge completed, the master branch contains all the work done in the editor branch, but the editor branch does not have any of the new work done on master. To synchronize the editor branch with the master branch we do git checkout editor; git merge master.

After merging master into editor branches

If there is no more editing to be done, it is acceptable to delete the editor branch. No code will be lost.

Because the ability to branch and merge is so quick and powerful, it is normal procedure to start a new branch for each issue being addressed in a project. When the issue is resolved, the new code is merged into master or discarded.

Remote Repositories

Is a tale for another time.

Conclusion

If you can use a source code control system to track your work and changes, do so. It makes life so much easier in the long term.

Common raven (Corvus corax) eating dead chicken. Wild life animal.

Eating Crow

Or “You don’t know what you don’t know.”

The short of this is that I’ve been building PCs for years. They are LEGO blocks. You make sure the parts will fit together, and it all just works.

As an example, I “knew” that LGA sockets were for Intel CPUs. Last night I learned that LGA just means the motherboard socket has the pins. PGA means the CPU holds the pins.

How did I learn this? I was researching AMD CPU sockets and learned that the AM4 socket was of the PGA style, while the AM5 socket is of the LGA type.

I didn’t know what I didn’t know.

We run a local data center. It is still a work in progress. We have enough disk space, but not enough redundancy. We have some compute servers, but not enough.

We try to do some upgrade every month, trying to improve things. The last improvement was another node in the Ceph Cluster.

After spending weeks researching, I found a 4 bay NAS enclosure that took Mini-ITX motherboards. This felt just about perfect.

It uses a flex style power supply, which is balanced for the actual load of 4 HDD and a motherboard. 350 Watts is what I went with. Thus, it draws less power than older machines.

Finding a Mini-ITX board was another research hell. What I wanted was MB with 4 SATA 3.0 ports, 1 or more SFP+ ports, one gigabit Ethernet port, at least 16 GB of memory and NVMe support for 512 GB of storage.

I couldn’t find one. I haven’t given up, but I haven’t found one yet.

After searching, I found a Mini-ITX MB with an LGA 1155 socket, 4 SATA2.0 ports, a 10/100 Ethernet Port, 2 DDR3 slots (16 GB), and a PCIe slot.

This might seem low end, but it meets our needs. HDDs only require 3 GB/s to keep up. We would need 3.0 if we were using SSDs.

The 10/100 is useless for moving data, but meets our needs for a management port. All in all, a good choice.

When all the parts arrived, I couldn’t get the MB installed. The fan was too tall. I got a better cooler that was a low profile style. When that came in, I installed the board. It was painfully tight getting everything in. Took me over an hour to get all the cables hooked up just right.

Everything went well until I went to put the cover back on. At that point, I found the cover didn’t fit “because the case had the motherboard too close to the edge.”

I fixed that in the machine shop. Grinders and cut off wheels to the rescue.

Everything goes together.

After everything is configured and running, I slap a drive into the case and it works. Wonderful. Final step? Install the SFP+ network card.

It doesn’t line up. The damn thing doesn’t line up with the slot in the back.

After mulling it over for way to long, I made the cut-out in the back wider and moved the standoffs. Machine shop to the rescue.

Except I had a bad network card. Easily fixed via a replacement. No big deal.

After over a month of fighting this thing, making massive changes to the case. Taking it entirely apart to get the motherboard in, the machine is now in production.

Yesterday the motherboard for an upgrade arrived. The case I bought to hold it had the PCI slot moved over. This looks like it will all just work.

Except that when I go to install the MB, I can’t get it to fit into the case. No big deal, I’ll take this case apart too.

But the board doesn’t line up. It doesn’t line up with the standoffs. It doesn’t line up with the back slot. It doesn’t even line up with the onboard I/O baffle.

At that point, I measured my Mini-ITX board. It should be 170mmx170mm. This board is not. It is 0.8 inches to wide. It isn’t a Micro-ITX nor is it a Mini-ITX. It is some none standard PoS.

I’m spitting mad at this point. I’ll put everything back in boxes until the new MB arrives. When it does arrive, I’ll be able to retire an older box that has been holding this data center back.

Everything now fits.

It wasn’t the case that was the issue with the last build. It was the motherboard. Time to update the reviews I wrote.

Coordinate Systems

When I started writing, regularly, for Miguel, I took it upon myself to cover legal cases. Since that time, I’ve learned more than I really wanted to about our justice system.

As my mentor used to say, “The justice system is just a system.” As a systems’ person, that allowed me to look at cases through the lens of my experience analyzing large systems.

One of the first things I noticed was that most people reporting on cases didn’t provide enough information for us to look up what was actually written or said.

CourtListener.com has come to my rescue for most legal filings in the federal system. If you know the court and the docket number you can find that case on CourtListener.

Once you have the docket located, you can start reading the filings. These are stored as PDFs. Most of my PDF tools allow me to copy and paste directly from the PDF.

What isn’t available on CourtListener is Supreme Court dockets. I’ve talked to Mike and others, the issue seems to be something about scrapping the Supreme Court website as well as other stuff. I’m not sure exactly what.

I want to be able to keep up on all the current cases in the Supreme Court, what their status currently is, what has been filed. They entirety of the case. I’m not concerned about most of the cases, but often it is easier to get all than a selected portion.

To this end, I have code that uses patterns to pull cases from the Supreme Court docket without have a listing of cases.

This tool will have search capabilities and other tools shortly, for now, it works well enough.

I am using the PySide6, which is a python implementation of the Qt framework. For the most part, I’m happy with this framework. There are parts I don’t like, which I work around.

My most recent success was figuring out how to allow me to click on hyperlinks in text to bring up my PDF viewer. This was not as simple as I wanted it to be, but it is working.

The other night, I wanted to write about a current case. I had the case docket in my tool. I pulled up the docket, clicked on the link, and John Roberts’ order popped up in my viewer, exactly as it should.

I started writing. Went to pull the quote and nothing.

Copy and paste does not seem to be functional in my tool.

Which takes me to the rant, which @#$)*&@$) coordinate system should I be using to get the right text!

Qt is built around widgets. Every widget has its coordinate system. In addition, there is the global coordinate system.

Each widget also has a paintEvent() which is when it paints itself.

To start the process, I capture mousePress, mouseMove, and mouseRelease events. While the mouse button is down, I draw a rectangle from the place clicked to the current location of the mouse.

I attempt to draw the rectangle and nothing shows up on the screen.

Through debugging code, I finally figured out that I am not updating the right widget.

The QPdfView widget properly renders the PDF document in a scrollable window. I have made a subclass of QPdfView so I am catching all paint events. But even though I’m telling the system that I have to redraw (update) my widget, there are no paint events being sent to my widget.

Turns out that my widget only cares about update signals that require the framing content be redrawn. I.e. if the scroll bar changes, then I get a paint event. Once I figured this out, I was able to tell the viewport that it should update and things started working.

So now I can draw a frame on the screen. But what I want is to get the text from within that frame.

I asked the QPdfDocument for a new selection from point_start to point_end. It tells me nothing is selected.

Where do I currently sit? I have my frame in my PDFViewer coordinate system. I have the PDF document in a different coordinate system. The PDF coordinate system is modified by the scroll bars or viewport. The scroll bars and scroll area modify the actual coordinate system of the viewport contents.

Somehow, I need to figure out which of these coordinate systems is the right coordinate system to use to get the text highlighted by my mouse.

I’m tired of this fight.

Historical one room school complete with dunce cap. Things have come a long way in the classroom.

Dunce of the Week

That would be me.

Everything finally came together with the new system. Then I went and messed it all up.

The motherboard has a weak Ethernet. It is a 10/100 Ethernet, which is NOT a problem for a management interface. When I upgrade the box to have full redundancy, it will get a dual port fiber card.

What it does mean is that my Wi-Fi to it via a USB dongle is faster than if I were to plug it in.

Once the box was in position, I connected via Wi-Fi and finished configuration. I tested all the connectivity, and it all just worked.

At that point, I told it to join the cluster. It did with pleasure, and brought the cluster to a stop.

Did you catch my mistake? Yeah, I left that dongle in.

At the bottom of the barrel, we have 10base-T. I have some old switches in boxes that might support that. Above that is 100base-T, which is a good management speed. We can move data for upgrades and restores, but not the fastest. Some of my switches and routers do not support 100baseT.

Above that is where we start to get into “real” speeds. Gigabit Ethernet, or GigE. I’ve now moved to the next step, which is ports supporting 10G over fiber or cable, depending on the module I use. The next step-up would be 25Gbit. I’m not ready for that leap of cost.

Wi-Fi sits at around 200Mbit/s. Faster than “fast Ethernet” also known as 100base-T, but not at “real” speeds. Additionally, Wi-Fi is shared space, which means that it doesn’t always give that much.

So what happened? The Ceph(NAS) cluster is configured over an OVN logical network on 10.1.0.0/24. All Ceph nodes live on this network. Clients that consume Ceph services will also attach to this network. No issues.

When you configure an OVN node, you tell the cluster what IP address to use for tunnels back to the new node. All well and good.

The 10G network connection goes to the primary router and from there to the rest of the ceph nodes. One of the subnets holds my work server. My work server provides 20Tb to the ceph cluster.

On that subnet are also the wireless access points.

So the new node correctly sent packets to all the ceph nodes via the 10G interface, EXCEPT for traffic to my work server. Why? Because the 10G had a 1 hop cost, while the Wi-Fi had a 0 hop cost. By routing standards, the 200Mbit Wi-Fi was the closer, faster, connection than the 1 hop 10G connections.

When I found the connection problem and recognized the issue, I unplugged the Wi-Fi dongle from the new node and all my issues cleaned up, almost instantly.