Note: lab2-harshgondaliya/lab/src/lab2
contains the key code files for the project. The following documentation explains the major software artifacts in the project.
A BinStore instance provides a BinStoreClient
that allows the user's front-end to perform Storage API calls to the user's virtual key-value store. Moreover, the BinStoreClient
also contains all the backend addresses, enabling the user's front-end to perform Storage API calls to any other user's virtual key-value store. A Keeper
process runs in the background that iteratively performs clock()
Storage API call to each backend server every one second. It ensures that logical clock at any backend server in a given iteration is set to at least the maximum logical clock value seen in last iteration plus 1.
Tribbler maintains a special bin named SIGNUP
in the bin storage that stores list of all the signed up users. Moreover, in each user's virtual key-value store, the following two keys are maintained to support various front-end operations:
tribs
: stores tribs posted by user.following_log
: stores the history offollow()
andunfollow()
operations that a user has performed in the order in which they reached the backend.
Note: To keep the documentation short, minute details like valid_username_check
, valid_trib_len
, is_signed_up
, is_who_equal_whom
etc are skipped and only the key functionality is described below.
The entire list of signed-up users is brought from the special SIGNUP
bin. If the user is not found in signed-up users list then his name is appended to signed-up users list in the SIGNUP
bin and the result is retured to client.
Each front-end caches a list of 20 users the first time it sees that at least 20 users have signed up. The front-end directly returns users cached in its memory if it contains 20 users. Otherwise, it will make RPC call to the user's bin and get the list of users.
A trib with its clock field set to the logical clock value is generated and appended to the user's tribs
list in the user's virtual key value store.
The entire tribs
list is fetched from the user's virtual key value store. The list is sorted in tribble order. If the user has posted less than equal to MAX_TRIB_FETCH
tribs then all the sorted tribs are returned to client. Otherwise, all but the last MAX_TRIB_FETCH
tribs in sorted list are removed from the backend, and the remaining MAX_TRIB_FETCH
tribs are returned to the client tribble order.
Note: The removal of all but the last MAX_TRIB_FETCH
tribs is just a garbage collection operation. Error message is not sent to the client if this garbage collection operation fails.
A log is maintained in the user's virtual key value store that stores the entire history of follow()
and unfollow()
operations that a user has done.
The following sequence of operations are performed:
- A log record for the current
follow()
operation is generated with the current logical clock value. - The log record is appended to the user's log list in the backend.
- The user's log list is fetched from the backend.
- All the
follow
andunfollow
operations are traced right from the beginning to determine what result should be returned to the client for the currentfollow()
operation that the client has invoked. Since all the log records are for the same user, our desiredfollow()
operation can be uniquely identified using the logical clock value that is present in the log records. - After tracing the log, if it is found that the current
follow()
will exceed theMAX_FOLLOWING limit
, then an error is returned to client. Otherwise, the result of currentfollow()
determined after tracing history of logs is returned to the client.
A log is maintained in the user's virtual key value store that stores the entire history of follow()
and unfollow()
operations that a user has done.
The following sequence of operations are performed:
- A log record for the current
unfollow()
operation is generated with the current logical clock value. - The log record is appended to the user's log list in the backend.
- The user's log list is fetched from the backend.
- All the
follow
andunfollow
operations are traced right from the beginning to determine what result should be returned to the client for the currentunfollow()
operation that the client has invoked. Since all the log records are for the same user, our desiredunfollow()
operation can be uniquely identified using the logical clock value that is present in the log records. - The result of current
unfollow()
determined after tracing history of logs is returned to the client.
A log is maintained in the user's virtual key value store that stores the entire history of follow()
and unfollow()
operations that a user has done.
The following sequence of operations are performed:
- The user's log list is fetched from the backend.
- All the follow and unfollow operations are traced right from the beginning to end to determine whether
who
is followingwhom
at the end of all the operations present in the log list. - The result after tracing history of logs is returned to the client.
A log is maintained in the user's virtual key value store that stores the entire history of follow()
and unfollow()
operations that a user has done.
The following sequence of operations are performed:
- The user's log list is fetched from the backend.
- All the
follow
andunfollow
operations are traced right from the beginning to end to determine all the users that the provided user is following after completion of all the operations present in the log list. - The result after tracing history of logs is returned to the client.
The following operations are performed:
- The entire
tribs
list of user is fetched from backend. The list is sorted in tribble order. If the user has posted less than equal toMAX_TRIB_FETCH
tribs then all the sorted tribs are appended to ahome_timeline
list. Otherwise, all but the lastMAX_TRIB_FETCH
tribs in sorted list are removed from the backend, and the remainingMAX_TRIB_FETCH
tribs are returned to the client tribble order. - The same three log operations mentioned above for
following()
function are performed to get the list of all users that the current user is following. Additionally, as a garbage collection step, all the unrequired log entries are removed from the backend. If this garbage collection step fails then error is not retured to client.
Note: Unrequired entries are the ones that whose presence does not affect the outcome derived by tracing history of follow and unfollow operations. Thus, while performing follow()
or unfollow()
if a user does not find his log record in the log then he can conclude that his operation is invalid and can return error to client.
- Step 1 mentioned above is performed for each user that the current user is following.
- Finally, home_timeline list is sorted in tribble order. If it has less than equal to
MAX_TRIB_FETCH
tribs then all the sorted tribs are returned. Otherwise, the lastMAX_TRIB_FETCH
are returned in tribble order.
Two kinds are garbage collection are being done:
- Removing the tribs older than MAX_TRIB_FETCH tribs: This is done in
tribs()
andhome()
function calls as described above. To avoid aggressive garbage collection invocations, we made a design choice to do it only in thehome()
function call and not in everypost()
function call. - Removing the unrequired log entries in following_log: This is done in
home()
function call as described above. To avoid aggressive garbage collection invocations, we made a design choice to do it only in thehome()
function call and not in everyfollow()
,unfollow()
,is_following()
, orfollowing()
function call.