{"id":19797122,"url":"https://github.com/joom/distributed-hash-table","last_synced_at":"2026-03-04T15:03:13.860Z","repository":{"id":77583452,"uuid":"75990459","full_name":"joom/distributed-hash-table","owner":"joom","description":"A Haskell implementation of distributed hash tables with two-phase commit.","archived":false,"fork":false,"pushed_at":"2016-12-09T02:11:53.000Z","size":56,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-10T03:25:35.695Z","etag":null,"topics":["deadlock","distributed-systems","haskell","heartbeat","lock","replicas"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-12-09T01:38:16.000Z","updated_at":"2023-04-28T18:55:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"f8bd60bb-ac70-4624-a693-7521bee1c9b1","html_url":"https://github.com/joom/distributed-hash-table","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/joom/distributed-hash-table","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joom%2Fdistributed-hash-table","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joom%2Fdistributed-hash-table/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joom%2Fdistributed-hash-table/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joom%2Fdistributed-hash-table/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joom","download_url":"https://codeload.github.com/joom/distributed-hash-table/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joom%2Fdistributed-hash-table/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30084685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T13:22:36.021Z","status":"ssl_error","status_checked_at":"2026-03-04T13:20:45.750Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deadlock","distributed-systems","haskell","heartbeat","lock","replicas"],"created_at":"2024-11-12T07:23:57.726Z","updated_at":"2026-03-04T15:03:13.834Z","avatar_url":"https://github.com/joom.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# distributed-hash-table\n\nA Haskell implementation of distributed hash tables with distributed two-phase commit.\nThe views can hold locks, and have replicas that they always communicate with to achieve quorum-based consensus.\n\nWritten as a project for COMP 360 Distributed Systems, Fall 2016, Prof. Jeff\nEpstein, Wesleyan University.\n\n![Diagram](http://i.imgur.com/Ao8MzVQ.png)\n\n## Installation\n\nMake sure you have [Stack](http://haskellstack.org) installed.\n\nClone the repository and run `stack install`. The executable files\n`dht-client`, `dht-server`, `dht-view-leader` must now be `~/.local/bin`, which\nis probably in your path variable.\n\n## Usage\n\nYou can run the server without any command line arguments: `dht-server`.\n\nFor `dht-client` and `dht-view-leader`, you can see all the options using the `--help` flag.\n\nThe executable  `dht-client` take optional arguments `--server` (or `-s`) and\n`--viewleader` (or `-l`) that specifies which host to connect , such a call\nwould be of the form\n\n```\ndht-client --server 127.0.0.1 setr \"lang\" \"Türkçe\"\n```\n\nThe executable `dht-server` also takes the `--viewleader` optional argument, to\nbe able to perform heartbeats.\n\nIf the optional argument `--server` isn't provided, it is assumed to be the local computer name.\n\nThe optional argument `--viewleader` (or with its short form `-l`) can be passed multiple times for each view replica, such as:\n\n```\ndht-view-leader -l mycomputer:39000 -l mycomputer:39001 -l mycomputer:39002 -l mycomputer:39003 -l mycomputer:39004\n```\n\nIf the optional argument `--viewleader` isn't provided, it is assumed that there are 3 default inputs: your computer name with the ports 39000, 39001 and 39002.\n\n### Timeouts\n\nIf a connection to a host name and a port, or a bind to a port doesn't happen\nin 10 seconds, you will get a timeout error and the program will try the next\navailable port number.\n\nIf a server fails to send a heartbeat for 30 seconds, but then later succeeds,\nit will be told by the view leader that it expired. In that case, the server\nterminates.\n\n### Locks and deadlock detection\n\n\nWhen there is a request for a lock that receives the retry message, that client\nis added to the queue for that lock. Even though the client stops asking, it will\nget the lock when the clients that are waiting in front of it in the queue get\nand release the lock.\n\nThe view leader assumes that a server crashed if it sends no heartbeat for 30\nseconds.  In that case, if that server holds any locks (that have the requester\nidentifier format `:38000`, where the number is the port) are cancelled\nautomatically.\n\nWhen the server has to return retry for a lock get request, it checks if there\nis a deadlock in the system by building a directed graph and looking for\ncycles. If there is, it logs the requesters and locks involved. Right now, it\nrepeatedly logs the same deadlock information as long as it keeps getting the\nrequest. Since the client keeps retrying by default, it will not stop logging\nthe deadlock unless the client is stopped. If a requester ID is used for\nmultiple lock requests at the same time, this can cause some weird behavior.\n\n*Deadlock detection is currently deactivated, will be reactivated after refactoring for consensus.*\n\n### Bucket allocator\n\nWe assume that our hash function evenly distributes strings to integers. We\ntake the UUID of every server to be the string for its hash, i.e. the hash\nvalue of the server. Therefore we assume that our servers more or less evenly\nsplit the number of keys we want to hold. The primary bucket to hold a key is\nthe bucket that has the server that has the lowest hash value that still is\nstrictly greater than the hash of the key string. We hold 2 more replicas as\nbackup, in servers that have the next 2 lowest hash value.\n\n### Rebalancing\n\nIf some servers are removed, then each server will check if the keys they\ncurrently hold used to reside in one of the servers that are removed.  If\nthat's the case, then it will make a request to the new server that is suppose\nto hold the data, to save the data.\n\nWhen there are new servers, each server will check what keys they have.  If a\nserver has a key that should reside in a different server now, it will make a\nrequest to that different server and then delete that key from itself.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoom%2Fdistributed-hash-table","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoom%2Fdistributed-hash-table","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoom%2Fdistributed-hash-table/lists"}