Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solved issue #18 - Add code examples for basic operations in README.md #35

Closed
wants to merge 5 commits into from
Closed
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
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,94 @@ More operations which will be added like `PeekMax`,`PopMax`,`PopMin` etc.
---


## Some simple primitive methods :

- [Read Operation](#)
- [Write Operation](#write-operation)
- [Keys Operation](#keys-operation)
- [Erase Operation](#erase-operation)
- [Put Operation](#put-operation)
---
1) Read Operation
---
```
package main

import "fmt"

func main() {
// Example data
data := map[string]string{
"key1": "value1",
"key2": "value2",
}

// Reading a value by key
value, exists := data["key1"]
if exists {
fmt.Println("Read value:", value) // Output: value1
} else {
fmt.Println("Key not found")
}
}
```
2) Wrire Operation
```
package main

import "fmt"

func main() {
// Example data
data := map[string]string{
"key1": "value1",
"key2": "value2",
}

// Reading a value by key
value, exists := data["key1"]
if exists {
fmt.Println("Read value:", value) // Output: value1
} else {
fmt.Println("Key not found")
}
}
```
3) Write Operation
```
package main

import "fmt"

func main() {
// Creating an empty map
data := make(map[string]string)

// Writing data to the map
data["key1"] = "value1"
fmt.Println("Data after write:", data) // Output: map[key1:value1]
}
```
4) Keys Operation
```
package main

import "fmt"

func main() {
// Example data
data := map[string]string{
"key1": "value1",
"key2": "value2",
}

// Retrieving all keys
fmt.Println("Keys in the map:")
for key := range data {
fmt.Println(key)
}
// Output:
// key1
// key2
}
```
75 changes: 75 additions & 0 deletions docs/MUTEX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# **MUTEXes Explained Like You're Five** 🚦

## **What’s a Mutex?**
Imagine you’re in a kitchen with one cookie jar, and all your friends want to grab a cookie at the same time. What would happen? LADAAI! Everyone’s hands get in the way, and high chances that the jar would fall and break.

A **mutex** (mutual exclusion) is like a **key to the cookie jar**. Only one person can hold the key at a time, which means only they can access the cookies. And when they’re done, they hand the key to the next person. This way, the cookie jar stays safe, and everyone gets their turn.

---

## **Mutex vs Semaphore: What’s the Difference?**
Let’s say you have two scenarios:


1. **The Cookie Jar (Mutex):**
Only one person can take cookies at a time. This is what a **mutex** does — it ensures **exclusive access** to shared resources.

2. **The Playground Swing (Semaphore):**
Imagine there are three swings, and a group of kids waiting to play. Up to three kids can swing at the same time, but no more. This is a **semaphore**, which allows multiple threads to access a resource, but only up to a fixed limit.

---


# **Understanding Mutexes in Go** 🚦

Mutexes are an essential tool in programming to avoid chaos when multiple threads or goroutines need access to shared resources. Think of them as the "key" that ensures only one thread can use a resource at a time. This README will walk you through how mutexes work, when to use them, and when to avoid them.

---

## **Core Operations?** 🤔

Here’s a breakdown of the core operations when using a mutex in Go:

| **Operation** | **Description** |
|--------------------------|------------------------------------------------------------------------------------------------------|
| `mutex.Lock()` | Locks the shared resource (e.g., `counter`), ensuring only one goroutine can update it at a time. |
| `mutex.Unlock()` | Unlocks the resource, allowing other goroutines to access it. |
| `sync.WaitGroup` | Helps synchronize the goroutines, ensuring the main program waits for all to finish before proceeding.|


## **Mutex Example in Go** 🚀

Here’s a practical example to demonstrate mutex usage:

```go
package main

import (
"fmt"
"sync"
)

var (
counter int // A shared resource
mutex sync.Mutex // A mutex to protect the resource
)

func increment(wg *sync.WaitGroup) {
mutex.Lock() // Acquire the lock
counter++ // Safely update the counter
mutex.Unlock() // Release the lock
wg.Done() // Mark this goroutine as done
}

func main() {
var wg sync.WaitGroup
wg.Add(3) // We’ll use three goroutines

for i := 0; i < 3; i++ {
go increment(&wg) // Start a goroutine
}

wg.Wait() // Wait for all goroutines to finish
fmt.Println("Final Counter:", counter)
}
```
65 changes: 32 additions & 33 deletions mermoria.go → memoria.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,64 +103,63 @@ func (m *Memoria) Write(key string, val []byte) error {

// writes the data given by the io.reader performs explicit sync if mentioned otherwise
// depedning on the physical media it sync
func (m *Memoria) WriteStream(key string, r io.Reader, sync bool) error {

func (m *Memoria) WriteStream(key string, r io.Reader, sync bool) error {
if len(key) <= 0 {
return fmt.Errorf("Empty key")
}

pathKey := m.transform(key)

//TODO: check for bad paths check if any part contains / after being transformed

m.mu.Lock()
defer m.mu.Unlock()

if err := m.createDirIfMissing(pathKey); err != nil {
return fmt.Errorf("Cannot create directory: %s", err)
}

f, err := m.createKeyFile(pathKey)

// created a temp file
tmpFile, err := os.CreateTemp(m.pathFor(pathKey), "tmp-*")
if err != nil {
return fmt.Errorf("cannot create key file: %s", err)
return fmt.Errorf("Cannot create temporary file: %s", err)
}
defer func() {
if _, err := os.Stat(tmpFile.Name()); err == nil {
os.Remove(tmpFile.Name()) // Cleanup temporary file
}
}()

wc := io.WriteCloser(&nopWriteCloser{f})

//TODO: replace wc with compression writer when implementing compression

// this is the place where data transfers actually happens when
// we transfer a read buffer to a writer
if _, err := io.Copy(wc, r); err != nil {
return cleanUp(f, fmt.Errorf("Cannot copy from read buffer %s", err))
// wrote data(in temp file)
if _, err := io.Copy(tmpFile, r); err != nil {
return cleanUp(tmpFile, fmt.Errorf("Cannot copy from read buffer: %s", err))
}

if err := wc.Close(); err != nil {
return cleanUp(f, fmt.Errorf("Cannot close compression error %s", err))
// close the temporary file
if err := tmpFile.Close(); err != nil {
return fmt.Errorf("Cannot close temporary file: %s", err)
}

// if sync {
// if err := f.Sync(); err != nil {
// cleanUp(f, fmt.Errorf("Cannot Sync: %s", err))
// }
// }
if err := f.Close(); err != nil {
return fmt.Errorf("Cannot close file: %s", err)
// renamed the temporary file to the target file
fullPath := m.completePath(pathKey)
if err := os.Rename(tmpFile.Name(), fullPath); err != nil {
return fmt.Errorf("Cannot rename temporary file to target file: %s", err)
}

//Atomic Writes: uncomment the following code when implemented atomic writes
// fullPath := m.completePath(pathKey)
// optional sync to ensure data is written to disk
if sync {
f, err := os.Open(fullPath)
if err != nil {
return fmt.Errorf("Cannot open file for syncing: %s", err)
}
defer f.Close()

// if f.Name() != fullPath {
// if err := os.Rename(f.Name(), fullPath); err != nil {
// os.Remove(f.Name())
// return fmt.Errorf("Cannot rename files: %s", err)
// }
// }
if err := f.Sync(); err != nil {
return fmt.Errorf("Cannot sync file: %s", err)
}
}

// empty the cache for original key
m.emptyCacheFor(pathKey.originalKey) // cache is read only
// Clear the cache for the original key
m.emptyCacheFor(pathKey.originalKey)

return nil
}
Expand Down