3232#include <stdlib.h>
3333#include <unistd.h>
3434#include <getopt.h>
35+ #include <inttypes.h>
3536
3637#include "priskv.h"
3738#include "priskv-log.h"
@@ -154,6 +155,7 @@ static void set_handler_base(client_context *ctx, char *args, bool alloc)
154155{
155156 char * key , * value , * opt , * opt_val , * str_end ;
156157 uint64_t expire_time_ms = 0 ;
158+ bool pin_on_seal = false;
157159 size_t valuelen ;
158160 priskv_sgl sgl ;
159161 priskv_status status ;
@@ -194,6 +196,9 @@ static void set_handler_base(client_context *ctx, char *args, bool alloc)
194196 if (!strcmp (opt , "EX" )) {
195197 expire_time_ms *= 1000 ;
196198 }
199+ } else if (!strcmp (opt , "PIN" )) {
200+ /* Redis-style: allow 'PIN' to indicate pin-on-seal */
201+ pin_on_seal = true;
197202 } else {
198203 printf ("%s\n" , invalid_args_msg );
199204 return ;
@@ -217,7 +222,7 @@ static void set_handler_base(client_context *ctx, char *args, bool alloc)
217222 printf ("ALLOC_SET status(%d): %s, addr %p, length %u, token 0x%lx\n" , status ,
218223 priskv_status_str (status ), (void * )region .addr , region .length , region .token );
219224 memcpy ((void * )region .addr , value , (size_t )region .length );
220- status = priskv_seal (ctx -> client , & region .token );
225+ status = priskv_seal (ctx -> client , & region .token , pin_on_seal );
221226 if (status != PRISKV_STATUS_OK ) {
222227 printf ("Failed to SEAL, status(%d): %s\n" , status , priskv_status_str (status ));
223228 return ;
@@ -269,7 +274,8 @@ static void get_handler_base(client_context *ctx, char *args, bool acquire)
269274 if (acquire ) {
270275 priskv_memory_region region = {0 };
271276 printf ("ACQUIRE key=%s\n" , key );
272- status = priskv_acquire (ctx -> client , key , PRISKV_KEY_MAX_TIMEOUT , & region );
277+ /* Do not pin on acquire by default from CLI */
278+ status = priskv_acquire (ctx -> client , key , PRISKV_KEY_MAX_TIMEOUT , false, & region );
273279 if (status != PRISKV_STATUS_OK ) {
274280 printf ("Failed to GET, status(%d): %s\n" , status , priskv_status_str (status ));
275281 return ;
@@ -279,7 +285,8 @@ static void get_handler_base(client_context *ctx, char *args, bool acquire)
279285 printf ("ACQUIRE GET status(%d): %s\n" , status , priskv_status_str (status ));
280286 printf ("ACQUIRE GET value[%u]=%s\n" , region .length , (char * )ctx -> buf );
281287
282- status = priskv_release (ctx -> client , & region .token );
288+ /* Do not unpin on release by default from CLI */
289+ status = priskv_release (ctx -> client , & region .token , false);
283290 if (status != PRISKV_STATUS_OK ) {
284291 printf ("Failed to RELEASE, status(%d): %s\n" , status , priskv_status_str (status ));
285292 return ;
@@ -384,6 +391,7 @@ static void seal_token_handler(client_context *ctx, char *args)
384391 char * tokstr , * str_end ;
385392 uint64_t token = 0 ;
386393 priskv_status status ;
394+ bool pin_on_seal = false;
387395
388396 tokstr = strtok_r (args , " " , & args );
389397 if (!tokstr ) {
@@ -400,7 +408,30 @@ static void seal_token_handler(client_context *ctx, char *args)
400408 return ;
401409 }
402410 }
403- status = priskv_seal (ctx -> client , & token );
411+ /* Parse optional flags: 'PIN [TTL <ms>]' */
412+ while (args && strlen (args ) > 0 ) {
413+ char * flag = strtok_r (args , " " , & args );
414+ if (!strcmp (flag , "PIN" )) {
415+ pin_on_seal = true;
416+ } else if (!strcmp (flag , "TTL" )) {
417+ /* TODO(wangyi): TTL passthrough is not implemented; parse and discard for now */
418+ char * ttl = strtok_r (args , " " , & args );
419+ if (!ttl || !strlen (ttl )) {
420+ printf ("%s\n" , invalid_args_msg );
421+ return ;
422+ }
423+ } else {
424+ printf ("%s\n" , invalid_args_msg );
425+ return ;
426+ }
427+ }
428+
429+ printf ("SEAL token=%" PRIu64 " [PIN=%d]\n" , token , pin_on_seal );
430+ /* TODO(wangyi): Support per-command TTL for pin-on-seal (e.g., 'PIN TTL N')
431+ * - Parse TTL value and pass through protocol once pin_ttl_ms is supported.
432+ * - Default to server-side TTL when not provided.
433+ */
434+ status = priskv_seal (ctx -> client , & token , pin_on_seal );
404435 printf ("SEAL status(%d): %s\n" , status , priskv_status_str (status ));
405436}
406437
@@ -409,15 +440,38 @@ static void acquire_only_handler(client_context *ctx, char *args)
409440 char * key ;
410441 priskv_status status ;
411442 priskv_memory_region region = {0 };
443+ bool pin_on_acquire = false;
412444
413445 key = strtok_r (args , " " , & args );
414446 if (!key ) {
415447 printf ("%s\n" , invalid_args_msg );
416448 return ;
417449 }
418450
419- printf ("ACQUIRE key=%s\n" , key );
420- status = priskv_acquire (ctx -> client , key , PRISKV_KEY_MAX_TIMEOUT , & region );
451+ /* Parse optional flags: 'PIN [TTL <ms>]' */
452+ while (args && strlen (args ) > 0 ) {
453+ char * flag = strtok_r (args , " " , & args );
454+ if (!strcmp (flag , "PIN" )) {
455+ pin_on_acquire = true;
456+ } else if (!strcmp (flag , "TTL" )) {
457+ /* TODO(wangyi): TTL passthrough is not implemented; parse and discard for now */
458+ char * ttl = strtok_r (args , " " , & args );
459+ if (!ttl || !strlen (ttl )) {
460+ printf ("%s\n" , invalid_args_msg );
461+ return ;
462+ }
463+ } else {
464+ printf ("%s\n" , invalid_args_msg );
465+ return ;
466+ }
467+ }
468+
469+ /* Align output field name with CLI flag semantics */
470+ printf ("ACQUIRE key=%s [PIN=%d]\n" , key , pin_on_acquire );
471+ /* TODO(wangyi): Support per-command TTL for pin-on-acquire (e.g., 'PIN TTL N')
472+ * - Parse TTL value and pass through protocol once pin_ttl_ms is supported.
473+ */
474+ status = priskv_acquire (ctx -> client , key , PRISKV_KEY_MAX_TIMEOUT , pin_on_acquire , & region );
421475 printf ("ACQUIRE status(%d): %s, addr %p, length %u, token 0x%lx\n" , status ,
422476 priskv_status_str (status ), (void * )region .addr , region .length , region .token );
423477 if (status == PRISKV_STATUS_OK ) {
@@ -434,6 +488,7 @@ static void release_token_handler(client_context *ctx, char *args)
434488 char * tokstr , * str_end ;
435489 uint64_t token = 0 ;
436490 priskv_status status ;
491+ bool unpin_on_release = false;
437492
438493 tokstr = strtok_r (args , " " , & args );
439494 if (!tokstr ) {
@@ -450,7 +505,22 @@ static void release_token_handler(client_context *ctx, char *args)
450505 return ;
451506 }
452507 }
453- status = priskv_release (ctx -> client , & token );
508+ /* Parse optional flags: 'UNPIN' */
509+ while (args && strlen (args ) > 0 ) {
510+ char * flag = strtok_r (args , " " , & args );
511+ if (!strcmp (flag , "UNPIN" )) {
512+ unpin_on_release = true;
513+ } else {
514+ printf ("%s\n" , invalid_args_msg );
515+ return ;
516+ }
517+ }
518+
519+ printf ("RELEASE token=%" PRIu64 " [UNPIN=%d]\n" , token , unpin_on_release );
520+ /* TODO(wangyi): Diagnostics for UNPIN_NOT_CLOSED and TTL interactions
521+ * - Consider printing hints when UNPIN_NOT_CLOSED occurs to aid debugging.
522+ */
523+ status = priskv_release (ctx -> client , & token , unpin_on_release );
454524 printf ("RELEASE status(%d): %s\n" , status , priskv_status_str (status ));
455525}
456526
@@ -475,6 +545,7 @@ static void drop_token_handler(client_context *ctx, char *args)
475545 return ;
476546 }
477547 }
548+ printf ("DROP token=% \n" PRIu64 , token );
478549 status = priskv_drop (ctx -> client , & token );
479550 printf ("DROP status(%d): %s\n" , status , priskv_status_str (status ));
480551}
@@ -649,14 +720,14 @@ static priskv_command commands[] = {
649720 {"set" , set_handler ,
650721 "set KEY VALUE [ EX seconds | PX milliseconds ]\tset key:value to priskv\n" },
651722 {"alloc_set" , alloc_set_handler ,
652- "alloc set KEY VALUE [ EX seconds | PX milliseconds ]\tset key:value to priskv \n" },
723+ "alloc_set KEY VALUE [ EX seconds | PX milliseconds ] [ PIN ]\tzero-copy set with optional pin on seal \n" },
653724 {"get" , get_handler , "get KEY\t\t\t\t\t\tget key:value from priskv\n" },
654725 {"acquire_get" , acquire_get_handler , "acquire get KEY\t\t\t\t\t\tget key:value from priskv\n" },
655726 {"alloc" , alloc_only_handler ,
656727 "alloc KEY BYTES [ EX seconds | PX milliseconds ]\t\tallocate region and print token\n" },
657- {"seal" , seal_token_handler , "seal TOKEN|last\t\t\t \t\tseal previously alloc'ed token\n" },
658- {"acquire" , acquire_only_handler , "acquire KEY\t\t\t\t \t\tacquire region and print token\n" },
659- {"release" , release_token_handler , "release TOKEN|last\t\t\t \t\trelease previously acquired token\n" },
728+ {"seal" , seal_token_handler , "seal TOKEN|last [ PIN [ TTL milliseconds ] ] \t\tseal previously alloc'ed token\n" },
729+ {"acquire" , acquire_only_handler , "acquire KEY [ PIN [ TTL milliseconds ] ] \t\tacquire region and print token\n" },
730+ {"release" , release_token_handler , "release TOKEN|last [ UNPIN ] \t\trelease previously acquired token\n" },
660731 {"drop" , drop_token_handler , "drop TOKEN|last\t\t\t\t\tDrop unpublished ALLOC token\n" },
661732 {"test" , test_handler , "test KEY\t\t\t\t\t\ttest if the key exists in priskv\n" },
662733 {"delete" , delete_handler , "delete KEY\t\t\t\t\t\tdelete the key from priskv\n" },
0 commit comments