Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 104 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,107 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# PyCharm files
.idea/

# C extensions
*.so
*.dylib

# Test binary, build with `go test -c`
*.test
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# mypy
.mypy_cache/
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Goredis Dockerfile

FROM golang:latest

MAINTAINER Alexander Gutyra <[email protected]>

RUN mkdir -p /go/src/GoHomework

COPY . /go/src/GoHomework

EXPOSE 9090
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Goredis Makefile

PROJECT_DIR_NAME = GoHomework

CLIENT_RUNFILE_PATH = client/runclient.go
SERVER_RUNFILE_PATH = server/runserver.go
CLIENT_TESTFILE_PATH = client/test/client_test.go
SERVER_TESTFILE_PATH = server/test/server_test.go

make_container:
sudo docker build -t goredis-app .
sudo docker run -d --rm -i --name goredis-app-running goredis-app

clear_dangling:
sudo docker rmi $$(sudo docker images -f "dangling=true" -q)

enter_container:
sudo docker exec -it goredis-app-running /bin/bash

stop_container:
sudo docker stop goredis-app-running


check:
go vet $(PROJECT_DIR_NAME)/server
go vet $(PROJECT_DIR_NAME)/client

build:
go build -o client/runclient $(CLIENT_RUNFILE_PATH)
go build -o server/runserver $(SERVER_RUNFILE_PATH)

test:
go test $(SERVER_TESTFILE_PATH)
go test $(CLIENT_TESTFILE_PATH)

.PHONY: runserver runclient
runserver:
./server/runserver

runclient:
./client/runclient
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Goredis

Goredis is a simple implementation of Redis on Golang.

## Getting started

### Requirements

All you need is a Docker app installed on your local computer.

### Installation

Clone or download this repository.

```git clone https://github.com/SamperMan44/GoHomework.git```

Build a docker image and run a Docker container by your own or using Makefile.

```make -f Makefile make_container```

Enter the terminal in your Docker container.

```make -f Makefile enter_container```

### Launching the server

Use Makefile to build and launch server with default params.

```
make -f Makefile build
make -f Makefile runserver
```

To get help on specified params, run server with argument `--help`.

```
~/go$ cd src/GoHomework/server
~/go/src/GoHomework/server$ go run runserver.go --help
```

### Launching the client

The client is launched by analogy with the server. Simply use `runclient` instead of `runserver`.

### Checking and testing

Run Makefile commands `check` and `test`.

## Available features

To get the list of available commands, run client and type `HELP`.

```
localhost:9090> HELP
Goredis is a simple implementation of Redis on Golang.
Available commands: HELP SET GET DEL KEYS (UN)SUBSCRIBE PUBLISH EXIT STOP.
To get more help on them, type any command with no arguments.
localhost:9090>
```

Launch `runserver.go` or `runclient.go` with `--help` argument to get usage manual.

Server modes: `disk` (saves your changes), `memory` (keeps loaded database only in RAM).
20 changes: 20 additions & 0 deletions client/client/argparser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package client

import "flag"

func GetCommandLineParams() (string, string, bool, string) {
var host, port, filename string
var dump bool

flag.StringVar(&host, "host", "localhost", "default connection host")
flag.StringVar(&host, "h", "localhost", "default connection host (shortcut)")
flag.StringVar(&port, "port", "9090", "connection port")
flag.StringVar(&port, "p", "9090", "connection port (shortcut)")
flag.BoolVar(&dump, "dump", false, "dump database into JSON format")
flag.BoolVar(&dump, "d", false, "dump database into JSON format (shortcut)")
flag.StringVar(&filename, "restore", "", "restore the database from the dumped file")
flag.StringVar(&filename, "r", "", "restore the database from the dumper file (shortcut)")
flag.Parse()

return host, port, dump, filename
}
83 changes: 83 additions & 0 deletions client/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package client

import (
"bufio"
"bytes"
"fmt"
"net"
"os"
"strings"
"time"
)

func HandleServerResponds(conn net.Conn, invitationMessage string, done chan string) {
scanner := bufio.NewScanner(conn)
for {
fmt.Print(invitationMessage + "> ")
ok := scanner.Scan()
if !ok {
done <- "\rServer closed the connection."
return
}

text := scanner.Text()
if text != "" {
fmt.Println(text)
} else {
fmt.Println()
}
}
}

func HandleUserRequests(conn net.Conn, done chan string) {
var buff bytes.Buffer
reader := bufio.NewReader(os.Stdin)
for {
for {
b, _ := reader.ReadByte()

if strings.Compare(string(b), "\t") == 0 {
// NOT IMPLEMENTED
}

buff.WriteString(string(b))
if strings.Compare(string(b), "\n") == 0 {
break
}
}

text := buff.String()
if strings.Compare(text, "EXIT\n") == 0 {
done <- "\rYou have been disconnected."
}

SendRequest(conn, text)
buff.Reset()
}
}

func SendRequest(conn net.Conn, text string) {
err := conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
if err != nil {
fmt.Println("ERROR: Cannot configure your request.")
}

_, err = conn.Write([]byte(text))
if err != nil {
fmt.Println("ERROR: Cannot send your request.")
}
}

// Returns the rest of the command if it exists. Unused due to unimplementation
// of Tab completion feature.
func CompleteCommand(commandPart string) string {
commands := [4]string{"SET", "GET", "PUBLISH", "SUBSCRIBE"}

for i := range commands {
if strings.HasPrefix(commands[i], commandPart) {
return commands[i][len(commandPart):]
}
}

return ""
}
1 change: 1 addition & 0 deletions client/client/data/restore.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"This file is created to test...":"database restore"}
Binary file added client/runclient
Binary file not shown.
41 changes: 41 additions & 0 deletions client/runclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Title: Goredis clientside
Description: Goredis is a simple implementation of Redis on Golang
by Gutyra A.
*/

package main

import (
"GoHomework/client/client"
"fmt"
"net"
"os"
)

const protocol = "tcp"

func main() {
host, port, dump, filename := client.GetCommandLineParams()
exitMsgChan := make(chan string)

conn, err := net.Dial(protocol, host + ":" + port)
if err != nil {
fmt.Println("ERROR: cannot connect to " + host + ":" + port)
os.Exit(1)
}

go client.HandleServerResponds(conn, host + ":" + port, exitMsgChan)
go client.HandleUserRequests(conn, exitMsgChan)

if filename != "" {
client.SendRequest(conn, "RESTORE \"" + filename + "\"\n")
}

if dump {
client.SendRequest(conn, "DUMP\n")
}

fmt.Println(<-exitMsgChan)
close(exitMsgChan)
}
Loading