Skip to content

Commit a68af8f

Browse files
committed
feat: 🎸 Support img display in mdx file
1 parent 65fa4a6 commit a68af8f

File tree

15 files changed

+502
-3
lines changed

15 files changed

+502
-3
lines changed

‎.DS_Store

6 KB
Binary file not shown.

‎blog/.DS_Store

6 KB
Binary file not shown.

‎blog/another-blog/icon.png

10.9 KB
Loading

‎blog/another-blog.mdx renamed to ‎blog/another-blog/index.mdx

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ date: "2021-07-24"
55
description: "Another blog test test test"
66
---
77

8-
Here's another post! It's even better than the first one!
8+
Here's another post! It's even better than the first one!
9+
![Hopper The Rabbit](./icon.png)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
title: "Database Design and Implementation Note"
3+
queryId: "database-design-and-implementation-note"
4+
date: "2021-10-09"
5+
description: "Notes for the book about database"
6+
tags: ["database", "note"]
7+
---
8+
9+
10+
11+
In this post, I will record the notes when reading the book Database design and implementation (Sciore 2020). It mainly includes the points I feel important or unclear before reading the book.
12+
13+
The current version starts from chapter 2 since chapter 1 is more like the environment and conclusion content. So let's start.
14+
15+
## Chapter 2 JDBC
16+
17+
### Concepts
18+
19+
***Database engine:*** database engine is the software which manages(create, update, delete) the database directly. It is a part of DBSM.
20+
21+
***Database client application:*** it is a software which calls the database engine's APIs to manipulate the database.
22+
23+
***JDBC:*** it is a set of formats which regulates how to write database engine's APIs with Java. JDBC contains five interfaces: *Driver, Connection,Statement, ResultSet, and ResultSetMetadata*.
24+
25+
Usually, the client application does not want to adapt to different format of engine API, instead it wants to use fixed APIs for several operations, like connecting to db, operating statement and receiving from database. So JDBC provides a regulation for all db engine - they must implement the interfaces to provide the required features.
26+
27+
### Connect to database with JDBC
28+
29+
The Driver interface in JDBC provides the method to connect client and database(connect).
30+
31+
It accepts the protocol of connection(who connects to who), location of the server(ip, path), and other arguments(authentication, create new or not).
32+
33+
#### Vendor-specific code in client program
34+
35+
Notice, even though JDBC provides the common format for all db engines, there is still vendor-specific command to call in JDBC client. The different db engines provide different Driver types, and to connect to server, the client must use those different Drivers. Also, when connecting to db, different engines require different connection string (to specify different configs). In this case, the Drive and the connection string in client may differ for different engines.
36+
37+
Because of the different types of Driver, in client program, it needs to import the engine specified Driver class.
38+
39+
#### Close a connection
40+
41+
The connection class provides a method close() which allows to close the connection between client and server.
42+
43+
### Exception Handle
44+
45+
There are various exception might happen during running database, different db engine usually handle them in different ways. So to regulate the exception showing for client, JDBC provides a exception class ***SQLException***, it wraps the db engine's personal exception and provides the client a error message according to the wrapped exception.
46+
47+
#### Try with resource syntax
48+
49+
```kotlin
50+
try (Connection conn = d.connect(url, null)){
51+
52+
} catch (SQLException e) {
53+
54+
}
55+
```
56+
57+
In this example, it creates a connection resource in try parentheses, when it reaches the end of try block, no matter it has a exception or finishing the execution, java will close the connection resource implicitly which avoids the resource leak.
58+
59+
### Executing SQL statements
60+
61+
After the connection is created, the connection class can use the method createStatement() to create a Statement object. The Statement has three basic methods --
62+
63+
executeQuery, executeUpdate and close.
64+
65+
- executeQuery's argument is a double quoted SQL query, and returns a ResultSet object.
66+
67+
- executeUpdate's argument is a double quoted SQL UPDATE query, and returns a ResultSet object.
68+
69+
- executeUpdate method returns the number of records that were updated.
70+
71+
- executeQuery method returns a ResultSet object which represents the output of the query.
72+
73+
#### RestultSet
74+
75+
It is a object used to store each row of the output after executing the SQL query. In the beginning it points to the position before the first row of output records. By calling the method next(), it can move one row forward. When pointing to each, the client can use some methods to call that row's record. When next() method returns False, it's pointing to the end of the output records.
76+
77+
```kotlin
78+
// connection
79+
String qry = "select ...";
80+
ResultSet rs = stmt.executeQuery(qry);
81+
while (rs.next()) {
82+
... // process the record
83+
// getString(fieldName)
84+
// getInt(fieldName)
85+
}
86+
```
87+
88+
### ResultSetMetaData
89+
90+
The interface ResultSetMetaData of JDBC can be used to record the information of each column (eg name, type, data size of each field in one table). It is the output of method `ResultSet.getMetaData();`
91+
92+
```kotlin
93+
// i is the index of column, starting from 1
94+
// use a loop to get all columns' infor
95+
String name = md.getColumnName(i);
96+
int size = md.getColumnDisplaySize(i);
97+
int typecode = md.getColumnType(i);
98+
```
99+
100+
### Whole process for a client to execute one SQL statement
101+
102+
1. Accept one connection string from the input, determine it's connecting to server or Embedded by checking if there is "//" in connection string. Then create the proper Driver.
103+
2. Using the Driver to create a connection, by calling ` Driver.connect(connStr, null)` , and put this call in try statement to prevent the resource leak.
104+
3. Initializing a Statement object, to prepare for executing statement later.
105+
4. Inside the try block, using while loop to accept each line of statement, operating bases on the start str of the statement:
106+
1. if starting with exit, close the connection, quit the process
107+
2. if starting with "select"
108+
1. Using the Statement object and query statement, calling ` stmt.executeQuery(SQLStatment)` and get the ResultSet object.
109+
2. Using loop and proper methods to get each column's info(type, name, size)
110+
3. Using loop and ResultSet.next() to get each row's record.
111+
3. if starting with other str
112+
1. Using the Statement object and query statement, calling ` stmt.updateQuery(SQLStatment)`
113+
2. Output how many records are updated
114+
115+
### Transaction
116+
117+
#### Autocommit or Not
118+
119+
A Transaction is a set of work (SQL statements). When a set of work is completed successfully, the database engine will commit the change to the db. When any work inside the transaction fails, the engine will fail all work of this transaction and roll back the db's state.
120+
121+
In the base JDBC implementation, the process implemented in a way called Autocommit, each statement is a transaction, so the engine will not commit multiple changes in one transaction.
122+
123+
This is reasonable since each transaction creates a lock which prevents the other transaction from committing, and executing one statement in each transaction will shorten the waiting time for the other transactions. But we may want the transaction to contain multiple work sometimes:
124+
125+
1. When we need more than one statement active. For example, if we need the result of the first statement to operate the second statement. If we release the lock after executing the first statement, the result might be different when executing the second statement. So we need to lock the resource during the whole process of executing these two statements.
126+
127+
2. When we need to execute more than one statement at the same time. For example, swapping two records:
128+
129+
```sql
130+
String cmd1 = "update SECTION set Prof= 'brando' where SectId = 43";
131+
String cmd2 = "update SECTION set Prof= 'einstein' where SectId = 53";
132+
```
133+
134+
If we commit the db after the first stmt, two names will be same and this is an undesirable result.
135+
136+
3. Because each stmt is independent, it might be inconvenient if we want to do a batch of work but it crashes in the middle of work. We have difficulty to determine which operations are successful and which failed. It's better to put them in one transaction and let them fail or succeed together.
137+
138+
#### Solution
139+
140+
To allow custom handle of commit/transaction, JDBC provides three APIs of Connection object for client.
141+
142+
```kotlin
143+
public void setAutoCommit(boolean ac) throws SQLException;
144+
public void commit() throws SQLException;
145+
public void rollback() throws SQLException;
146+
```
147+
148+
By calling ` setAutoCommit(False)`, it closes the engine's one stmt each transaction strategy, giving the client rights to decide when to commit or rollback. Then the client can decide the time to complete the transaction by itself.
149+
150+
After all statements in one desired transaction is finished, the client can call commit(), and the client can call rollback() in catch block of the try statement of creating the connection, so that if any error happens, it can roll back the db.
151+
152+
### Handle concurrency
153+
154+
The concurrency in database is similar as it in operating system -- db engines handle the one transaction(process) first, stop it and move to handle another transaction(process), and move among different transactions. Similar as CPU, db engines cannot handle multiple transaction at the same time, instead, it stops one transaction, stores its states, and move to the other transactions. With the fast speed, it creates an illusion that it's handling multiple transaction at same time.
155+
156+
This leads to problem, because if part of one transaction is finished, and another transaction start to executing the stmts, it will use the wrong, uncommitted records created by the first transaction.
157+

‎blog/intro-to-express/index.mdx

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
title: "Intro to Express"
3+
queryId: "intro-to-express"
4+
date: "2020-08-02"
5+
description: "My first touch with Nodejs and Express."
6+
tags: ["backend", "express", "introduction"]
7+
---
8+
9+
### What is Express?
10+
11+
Express is a Web framework based on node.js. It provides ways to recognize and respond to http request through Middleware and Router.
12+
13+
### Start
14+
15+
To start using Express, we need to import express and create one instance using express(). To test the application, we also need a port and use the instance to listen to the port. This port can replace the real root dir and simulate the root page of the application.
16+
17+
```jsx
18+
const express = require('express')
19+
const app = express()
20+
const port = 3000
21+
22+
app.listen(port, () => {
23+
console.log(`Example app listening at http://localhost:${port}`)
24+
})
25+
```
26+
27+
### Routing
28+
29+
Routing is the way to determining the response to the particular request. A route needs one method (GET, POST, PUT), one path and one or more handler callback function(s). An example is:
30+
31+
```jsx
32+
app.get('/', function(req, res))
33+
```
34+
35+
The path represents the location of the request requires to change. The req object represents the HTTP request and res represents the HTTP response that the app will send when it receive a request.
36+
37+
### Serving static files
38+
39+
The work of the web application is the process of requests and responses. For example, when we open the main page of one web app, we send a request to GET index.html as a client. If such file is right in local dir, we can use express to get it directly as a static file. For example, if all our front-end file is in the dir path '~/build', we can use
40+
41+
```jsx
42+
app.use(express.static('build'))
43+
```
44+
45+
In this case, whenever the server receives the request to GET something, it will go to the build folder and look for the responded file. If there is no such file locally, Express will then go to the connected database to look for it through some condition (model schema).
46+
47+
### Middleware
48+
49+
Middleware functions are functions that have access to req, res and the 'next' function. There are five types of middleware. The next function can assign the direction of the flow. If the middleware does not end the req, res cycle, a next() function is required to continue the flow into the next middleware function.
50+
51+
#### Application-level middleware
52+
53+
This middleware includes two methods, app.use() and app.METHOD().
54+
55+
If the app.use() only has one argument, the callback function, it will be executed every time the app receives a request. If there is the path in the arguments, the function will executed every time the app receives a request on the path.
56+
57+
#### Router-level middleware
58+
59+
The router middleware needs to be bound to an instance of "require('express').Router()". It can be seen as a middleware between app middleware and router. The RLM can only perform middleware and routing functions. After we bound the RLM to some routers, we can execute app.use(path, router_instance) and that will execute the corresponding method we bound to RLM instance.
60+
61+
#### Error-handling middleware
62+
63+
Whenever we catch some error in the middleware and route handlers, we need to pass the error to Express through next(error). The error will then be passed into the build-in error handler. We can also write error handlers and this is the error-handling middleware.
64+
65+
```jsx
66+
app.use(function(err, req, res, next) {})
67+
```
68+
69+
We can handle different errors inside the function, and in the end, we can continue to use next(error) to pass the error we cannot handle now to Express.
70+
71+
### Handle unknown endpoints
72+
73+
If the client send an request which is not defined in any middleware, we need to handle it by responding a 404. The way to handle writing and adding an unknown endpoint middleware after all app-level middleware and router-level middleware and before Error-handling middleware.
74+
75+
```jsx
76+
app.use((request, response) => {
77+
response.status(404).send({ error: 'unknown endpoint' })
78+
})
79+
```
80+
81+
To learn more about Express, view [API reference](https://expressjs.com/en/5x/api.html).

‎blog/mit-6828-lab1-note/index.mdx

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: MIT 6.828 Lab 1 Note
3+
queryId: "mit-6828-lab1-note"
4+
date: "2020-12-22"
5+
description: "MIT OS course lab note"
6+
tags: ["operating system", "note"]
7+
---
8+
9+
## Introduction
10+
11+
From today, I am going to share my experience in learning, implementing labs of MIT 6.828 in my blog.
12+
13+
My background knowledge includes: C, computer architecture, RISC-V.
14+
15+
I am going to use 2018 version material simply because there are most amount of resource about this version online.
16+
17+
[Course homepage](https://pdos.csail.mit.edu/6.828/2018/schedule.html)
18+
19+
[lab1 page](https://pdos.csail.mit.edu/6.828/2018/labs/lab1/)
20+
21+
## Environment setup
22+
23+
First clone the course git repo, [Course Git reop](https://pdos.csail.mit.edu/6.828/2018/jos.git). Then install toolchain, [install instruction](https://pdos.csail.mit.edu/6.828/2018/tools.html). Note that if the Compiler Toolchain is already installed, the only thing needs to be installed is QEMU emulator. Next, lets compile the files in the Git repo.
24+
25+
```bash
26+
sudo apt install gcc-multilib # if you are not under 32 bit environment
27+
cd lab
28+
make
29+
```
30+
31+
Then type
32+
33+
```bash
34+
make qemu
35+
```
36+
37+
We will successfully start JOS in the QEMU emulator. Now we boot the template OS and finish the setup of environment and lets take a look at the memory distribution in 32-bit machine.
38+
39+
## PC'S address space & PC start up process
40+
41+
![PC's physical address](./pcmemory.png)
42+
43+
The important part for PC start up is only the lower 1MB part, because right now CPU is under Real mode and the only accessible memory is this part. In this part, the most important on is BIOS (basic IO system), because code in BIOS starts the normal PC start up. And the other part of this 1MB memory is mapped by peripherals, which means CPU can read/write the other part to manipulate peripherals.
44+
45+
#### An interesting history
46+
47+
The max memory 32-bit processor can handle is 4GB. So when the 64-bit processor came out, larger memory were used in PC. The modern PC usually put BIOS at the top of the memory, and to keep the backward compatibility for some old software, designer keeps a "hole" from 0x000A0000 to 0x00100000.
48+
49+
### Use GDB to analyze the process of start up
50+
51+
Now open two terminals, move into the OS folder. In the first one, type
52+
53+
```bash
54+
make qemu-nox-gdb
55+
```
56+
57+
This line starts the emulator and waits for the connection of GDB. And in the second terminal, type
58+
59+
```bash
60+
make gdb
61+
```
62+
63+
This line starts GDB and connect it to the OS. The file .gdbinit configs GDB to debug the code executed in the boot of OS in QEMU.
64+
65+
#### Very first instruction
66+
67+
```bash
68+
[f000:fff0] 0xffff0: ljmp $0x3630,$0xf000e05b
69+
```
70+
71+
This is the first line appears after we connect GDB and OS. It shows where does the processor fetch the very first instruction and what that instruction is when we boot a PC.
72+
73+
Under the real mode, address is in the form of (segment base : offset). So in the above line, in [f000:fff0], 0xf000 is segment base and 0xfff0 is offset. For 0x3630, 0xf000e05b, 0x3630 is segment base and 0xf000e05b is offset. The way to transfer this form into physical form is:
74+
75+
```plain
76+
phyAddr = 16 * segment + offset = 16 * CS + IP
77+
```
78+
79+
And after translating, this line means the professor fetch instruction from address 0xFFFF0, and instruction inside is a jump instruction, and the target address is 0xF004 435B.
80+
81+
So there is several natural questions:
82+
83+
1. Why did the designer put the very first instruction in this location (distance between here and end of BIOS is 0x100000 - 0xFFFF0 = 16 bytes)?
84+
2. Why don't just put this instruction in the beginning of the BIOS?
85+
3. Considering it is a jump instruction, why not set the first instruction just at its target address?
86+
87+
The first two questions can be answered together. We have to consider that each PC company has their own BIOS code, user can add BIOS code too. Also, different company designs different length of BIOS boot code, so if the user wants to add code, the place to add is uncertain. However, if instead, we put user created code in the beginning of BIOS, it is more convenient to manage. So normally we put BIOS boot code in the end of BIOS part.
88+
89+
For the last question, because different PC has different length of BIOS boot code, for example, if this code is 1KB, the start address is 0x100000 - 0x400 = 0xFFC00. If the code is 2KB, the start address is 0xFF800. And it is not a good practice to adjust the first instruction address in each PC. So the rule is put a jump instruction at 0xFFFF0 and the target is defined by each company.
90+
91+
## TO BE CONTINUE
15.2 KB
Loading
93.3 KB
Loading

0 commit comments

Comments
 (0)