Skip to content

feichai0017/m-zodic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project Overview

This repository implements a collaborative Markdown editor comprised of three main layers:

  1. Markdown Library - immutable editing core
  2. Client - terminal-based user application
  3. Server - multi-threaded coordinator, command queue, versioned broadcast

1. Markdown Library - Design & Implementation

1.1 Data Model

Name Purpose
chunk Smallest text unit - stores text, length, type
document Doubly-linked list of chunks + version fields
del_range[] Tracks ranges deleted within current version
 document ├─ committed_head ─> [chunk] - committed content (read-only) ├─ head ─> [chunk] - WIP edits └─ del_ranges[] deferred deletions 
  • Committed state - immutable snapshot of version N
  • WIP state - edits for next version, lazily initialised

1.2 Editing Primitives

All public API functions follow the same pattern:

  1. markdown_ensure_wip() - copy committed list on first edit
  2. Adjust cursor using del_ranges helpers
  3. Perform edit (insert, delete, heading …)
  4. Consolidate text chunks to keep list compact

Return codes are SUCCESS / INVALID_CURSOR_POS / … defined in common.h.

1.3 Versioning

  • markdown_increment_version() commits the WIP list
  • committed_version is incremented, WIP pointers reset
  • markdown_flatten() always serialises the committed list → guarantees that only committed content is exposed to file/network.

1.4 Horizontal rule helper

markdown_horizontal_rule() inserts --- and lazily adds a trailing \n only when required, respecting block-element newline rules.


2. Client - Design & Implementation

2.1 Connection Protocol

  1. Signal handshake
    client sends SIGRTMIN → server
    waits for SIGRTMIN+1
  2. FIFO pair
    FIFO_C2S_<pid> - write commands
    FIFO_S2C_<pid> - read broadcasts / replies
  3. Authentication
    sends <username>\n, receives read / write or Reject UNAUTHORISED.
  4. Document bootstrap
    reads role, version, length, then full content → loads into local_doc without incrementing version.

2.2 Local State

struct client { uint64_t current_version; // server version we believe in document *local_doc; // local committed copy ... };

2.3 Threads

  • Main thread - CLI loop, sends commands, prints DOC?/LOG?/PERM?
  • Broadcast thread - consumes FIFO_S2C, parses
    • read / write → signals PERM? response
    • VERSION NEND broadcast → process_broadcast_message()

2.4 Broadcast Processing Logic

  1. Append every line to local log (linked list)
  2. For each EDIT … SUCCESS line
    • call matching markdown_… using the document's current committed version
    • set edits_applied = true when edit succeeds
  3. After END
    • if edits_applied - call markdown_increment_version() so DOC? sees the update
    • set local_doc->committed_version = target_version
    • set current_version = target_version

The client never invents a new version number - it adopts the server's.


3. Server - Design & Implementation

3.1 Core Data Structures

Structure Role
global_doc Authoritative committed document
command_queue_t Thread-safe FIFO of pending client commands
active_client_list Singly linked list of live client_session nodes
server_log_t Linked list storing every broadcast for LOG? requests

All shared structures are protected by mutexes.

3.2 Server Log

struct version_log_entry { uint64_t version_number; char *broadcast_message; // full multi-line VERSION … END block ... };
  • add_log_entry() - append under mutex
  • print_server_log() - dump to stdout on LOG? (admin)
  • Used to replay history for new clients (LOG? from client).

3.3 Command Queue

  • command_queue_push() - O(1) enqueue from client threads
  • command_queue_drain() - main thread atomically grabs whole list each interval
  • Commands carry client_doc_version to enforce version rules.

3.4 Client Session Thread

  1. Creates FIFOs & sends role + initial document (version, length, content)
  2. Reads commands line-by-line:
    • Metadata: PERM?, DOC?, LOG?, DISCONNECT
    • Edit commands pushed into command_queue
  3. Read-only users are pre-labelled UNAUTHORISED before push.

3.5 Main Loop (server.c:main)

while (!shutdown) { select(stdin, timeout = interval) → handle admin commands (QUIT / DOC? / LOG?) drain command_queue sort by timestamp for each cmd { version check & execute via Markdown API } if edits made → markdown_increment_version(global_doc) build broadcast "VERSION N\nEDIT …\nEND\n" add_log_entry() broadcast_to_all_clients() } 
  • Interval Timing - sleeps via select timeout specified by CLI argument.
  • Broadcast - written to every client_session->fd_s2c; clients update in their broadcast thread.

Build & Run

# Build default (COMP2017) version make clean && make all #build (COMP9017) version make comp9017 # Start server ./server <TIME-INTERVAL> # Start client ./client <SERVER_PID> <USER_NAME>

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors