syslog_rs/sync/
syslog_sync_shared.rs

1/*-
2 * syslog-rs - a syslog client translated from libc to rust
3 * 
4 * Copyright 2025 Aleksandr Morozov
5 * 
6 * The syslog-rs crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
10 *
11 *   2. The MIT License (MIT)
12 *                     
13 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
14 */
15
16use std::marker::PhantomData;
17use std::sync::Arc;
18use std::{str};
19
20use instance_copy_on_write::ICoW;
21
22use crate::formatters::DefaultSyslogFormatter;
23use crate::sync::syslog_stream::SyStreamApi;
24use crate::sync::{LogItems, SyStream};
25use crate::{formatters::SyslogFormatter, map_error_code};
26use crate::{common::*, SyslogDestination};
27use crate::error::SyRes;
28
29
30use crate::sync::syslog_sync_internal::{SyslogSocket};
31
32#[cfg(target_family = "unix")]
33use crate::SyslogLocal;
34
35#[cfg(target_family = "windows")]
36use crate::WindowsEvent;
37
38use super::syslog_trait::SyslogApi;
39
40#[cfg(target_family = "unix")]
41pub type DefaultLocalSyslogDestination = SyslogLocal;
42#[cfg(target_family = "windows")]
43pub type DefaultLocalSyslogDestination = WindowsEvent;
44
45/// A `sync`, shared instance of the syslog client which is shared between many
46/// threads. Previously a mutex was used, but since the v5.0.0 a CoW experimental
47/// approach is used. The `CoW` creates clones of the instance without holding
48/// a long mutex locks. When writing, the instance does not hold a long lock on
49/// updated item. Only exclusive lock locks the readers, because the instance is
50/// updated and not usable anyway.
51/// 
52/// If the program has fixed amount of threads, probably the `syslog_threadlocal`
53/// will be better alternative. It has the same functionality, but avoids 
54/// any sync locks by working in current thread.
55/// 
56/// # Traits
57/// 
58/// For this isntance a [SyslogApi] and [SyStreamApi] are implemented.
59/// 
60/// # Examples
61/// 
62/// ```ignore
63/// let log = 
64///     SyncSyslog::openlog(
65///         Some("test1"), 
66///         LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
67///         LogFacility::LOG_DAEMON,
68///         SyslogLocal::new()
69///     );
70/// ```
71/// 
72/// ```ignore
73/// let log = 
74///     SyncSyslog
75///         ::<DefaultSyslogFormatter, SyslogLocal>
76///         ::openlog_with(
77///             Some("test1"), 
78///             LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
79///             LogFacility::LOG_DAEMON,
80///             SyslogLocal::new()
81///         );
82/// ```
83/// 
84/// ```ignore
85/// pub static SYSLOG3: LazyLock<SyncSyslog<DefaultSyslogFormatter, SyslogLocal,>> = 
86///     LazyLock::new(|| 
87///         {
88///             SyncSyslog
89///                 ::<DefaultSyslogFormatter, SyslogLocal>
90///                 ::openlog_with(
91///                     Some("test1"), 
92///                     LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
93///                     LogFacility::LOG_DAEMON,
94///                     SyslogLocal::new()
95///                 )
96///                 .unwrap()
97///         }
98///     );
99/// ```
100/// # Streaming
101/// 
102/// A stream is availble via [SyStreamApi].
103/// 
104/// ```ignore
105/// let _ = write!(SYSLOG.stream(Priority::LOG_DEBUG), "test {} 123 stream test ", d);
106/// ```
107/// 
108/// # Generics
109/// 
110/// * `F` - a [SyslogFormatter] which sets the instance which would 
111///     format the message.
112/// 
113/// * `D` - a [SyslogDestination] instance which is either:
114///     [SyslogLocal], [SyslogFile], [SyslogNet], [SyslogTls]. By
115///     default a `SyslogLocal` is selected.
116#[derive(Debug, Clone)]
117pub struct SyncSyslog<F = DefaultSyslogFormatter, D = DefaultLocalSyslogDestination>
118where 
119    F: SyslogFormatter, 
120    D: SyslogDestination, 
121{   
122    /// An identification i.e program name, thread name
123    log_items: Arc<ICoW<LogItems>>,
124
125    /// A stream (unixdatagram, udp, tcp)
126    stream: Arc<SyslogSocket<D>>,
127
128     _p: PhantomData<F>,
129}
130
131unsafe impl<F: SyslogFormatter, D: SyslogDestination> Send for SyncSyslog<F, D>
132{}
133
134impl SyncSyslog
135{
136    /// Opens a default connection to the local syslog server with default formatter.
137    /// 
138    /// In order to access the syslog API, use the [SyslogApi].
139    /// 
140    /// # Arguments
141    /// 
142    /// * `ident` - A program name which will appear on the logs. If none, will be determined
143    ///     automatically.
144    /// 
145    /// * `logstat` - [LogStat] an instance config.
146    /// 
147    /// * `facility` - [LogFacility] a syslog facility.
148    /// 
149    /// * `net_tap_prov` - a [SyslogLocal] instance with configuration.
150    /// 
151    /// # Returns
152    /// 
153    /// A [SyRes] is returned ([Result]) with: 
154    /// 
155    /// * [Result::Ok] - with instance
156    /// 
157    /// * [Result::Err] - with error description.
158    pub 
159    fn openlog(ident: Option<&str>, logstat: LogStat, facility: LogFacility, 
160        net_tap_prov: DefaultLocalSyslogDestination) -> SyRes<Self> 
161    {
162        return Ok( 
163            Self
164            {
165                log_items: 
166                    Arc::new(
167                        ICoW::new(
168                            LogItems::new(ident, 0xff, logstat, facility)
169                        )
170                    ),
171                stream: 
172                    Arc::new(
173                        SyslogSocket::<DefaultLocalSyslogDestination>::new(logstat, net_tap_prov)?
174                    ),
175                _p: 
176                    PhantomData,
177            }
178        );
179    }
180}
181
182
183impl<F: SyslogFormatter, D: SyslogDestination> SyncSyslog<F, D>
184{
185    /// Opens a special connection to the destination syslog server with specific formatter.
186    /// 
187    /// All struct generic should be specified before calling this function.
188    /// 
189    /// In order to access the syslog API, use the [SyslogApi].
190    /// 
191    /// # Arguments
192    /// 
193    /// * `ident` - A program name which will appear on the logs. If none, will be determined
194    ///     automatically.
195    /// 
196    /// * `logstat` - [LogStat] an instance config.
197    /// 
198    /// * `facility` - [LogFacility] a syslog facility.
199    /// 
200    /// * `net_tap_prov` - a destination server. A specific `D` instance which contains infomation 
201    ///     about the destination server. See `syslog_provider.rs`.
202    /// 
203    /// # Returns
204    /// 
205    /// A [SyRes] is returned ([Result]) with: 
206    /// 
207    /// * [Result::Ok] - with instance
208    /// 
209    /// * [Result::Err] - with error description.
210    pub 
211    fn openlog_with(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self> 
212    {
213        return Ok( 
214            Self
215            {
216                log_items: 
217                    Arc::new(
218                        ICoW::new(
219                            LogItems::new(ident, 0xff, logstat, facility)
220                        )
221                    ),
222                stream: 
223                    Arc::new(
224                        SyslogSocket::<D>::new(logstat, net_tap_prov)?
225                    ),
226                _p: 
227                    PhantomData,
228            }
229        );
230    }
231}
232
233
234impl<F: SyslogFormatter, D: SyslogDestination> SyslogApi<F, D> for SyncSyslog<F, D>
235{
236    fn connectlog(&self) -> SyRes<()>
237    {
238        return 
239            self
240                .stream
241                .connectlog();
242    }
243
244    fn setlogmask(&self, logmask: i32) -> SyRes<i32> 
245    {
246        let mut transaction = 
247            self
248                .log_items
249                .as_ref()
250                .clone_copy();
251                /*.map_err(|e|
252                    map_error_code!(CoWExclLock, "set logmask failed with: {}", e)
253                )?;*/
254
255        let pri = 
256            transaction
257                .set_logmask(logmask);
258
259        transaction
260            .commit()
261            .map_err(|e|
262                map_error_code!(CoWWriteError, "set logmask failed with: {}", e.0)
263            )?;
264
265        return Ok(pri);
266    }
267
268    fn closelog(&self) -> SyRes<()> 
269    {
270        return 
271            self
272                .stream
273                .disconnectlog();
274    }
275
276    #[inline]
277    fn syslog(&self, pri: Priority, fmt: F) 
278    {
279        let Some((formatted_msg, logstat)) = 
280            self.log_items.read().vsyslog1_msg::<F, D>(pri, &fmt)
281            else { return };
282
283        self.stream.vsyslog1(logstat, formatted_msg);
284
285        return;
286    }
287
288    /// This function can be used to update the facility name, for example
289    /// after fork().
290    /// 
291    /// # Arguments
292    /// 
293    /// * `ident` - a new identity (up to 48 UTF8 chars)
294    fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
295    {
296        let mut clonned = 
297            self
298                .log_items
299                .as_ref()
300                .clone_copy();
301                /*.map_err(|e|
302                    map_error_code!(CowTransactionFailed, "change_identity to '{:?}' was not completed due to error: '{}'", ident, e)
303                )?;*/
304
305        clonned.set_identity(ident);
306
307        clonned
308            .commit()
309            .map_err(|e|
310                map_error_code!(CoWWriteError, "cannot change_identity due to exclusive lock, err: '{}'", e.0)
311            )?;
312
313        return Ok(());
314    }
315
316    fn reconnect(&self) -> SyRes<()>
317    {
318        return
319            self
320                .stream
321                .reconnectlog();
322    }
323
324    fn update_tap_data(&self, tap_data: D) -> SyRes<()>
325    {
326        return
327            self
328                .stream
329                .update_tap_data(tap_data);
330    }
331
332}
333
334impl<'stream, F: SyslogFormatter, D: SyslogDestination> SyStreamApi<'stream, F, D, SyncSyslog<F, D>> 
335for SyncSyslog<F, D>
336{
337    fn stream(&'stream self, pri: Priority) -> SyStream<'stream, D, F, SyncSyslog<F, D>> 
338    {
339        return 
340            SyStream 
341            { 
342                inner: self, 
343                pri: pri, 
344                _p: PhantomData, 
345                _p1: PhantomData 
346            };
347    }
348}
349
350#[cfg(target_family = "unix")]
351#[cfg(test)]
352mod tests
353{
354    use crate::
355    {
356        LogFacility, LogStat, Priority, SyStreamApi, SyncSyslog, SyslogApi, SyslogLocal 
357    };
358
359    #[test]
360    fn test_single_message()
361    {
362
363        let log = 
364            SyncSyslog::openlog(
365                Some("test1"), 
366                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
367                LogFacility::LOG_DAEMON,
368            SyslogLocal::new()
369        );
370
371        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
372
373        let log = log.unwrap();
374
375        let msg1 = format!("test UTF-8 проверка BOM UTF-8");
376        let now = std::time::Instant::now();
377
378        log.syslog(Priority::LOG_DEBUG, msg1.into());
379
380        let dur = now.elapsed();
381        println!("{:?}", dur);
382
383        let msg2 = format!("test UTF-8  きるさお命泉ぶねりよ日子金れっ");
384
385        let now = std::time::Instant::now();
386
387        log.syslog(Priority::LOG_DEBUG, msg2.into());
388
389        let dur = now.elapsed();
390        println!("{:?}", dur);
391
392        let _ = log.closelog();
393
394        return;
395    }
396
397    #[test]
398    fn test_single_stream_test()
399    {
400        use std::fmt::Write;
401
402        let log = 
403            SyncSyslog::openlog(
404                Some("test1"), 
405                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
406                LogFacility::LOG_DAEMON,
407            SyslogLocal::new());
408
409        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
410
411        let log = log.unwrap();
412        
413        write!(log.stream(Priority::LOG_DEBUG), "test123").unwrap();
414
415    }
416
417    #[test]
418    fn test_single_message_withound_nd()
419    {
420
421        let log = 
422            SyncSyslog::openlog(
423                Some("test1_nond"), 
424                LogStat::LOG_CONS | LogStat::LOG_PID, 
425                LogFacility::LOG_DAEMON,
426            SyslogLocal::new());
427
428        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
429
430        let log = log.unwrap();
431
432        let msg1 = format!("test UTF-8 проверка BOM UTF-8");
433        let now = std::time::Instant::now();
434
435        log.syslog(Priority::LOG_DEBUG, msg1.into());
436
437        let dur = now.elapsed();
438        println!("{:?}", dur);
439
440        let msg2 = format!("test UTF-8  きるさお命泉ぶねりよ日子金れっ");
441
442        let now = std::time::Instant::now();
443
444        log.syslog(Priority::LOG_DEBUG, msg2.into());
445
446        let dur = now.elapsed();
447        println!("{:?}", dur);
448
449        let _ = log.closelog();
450
451        return;
452    }
453
454    #[test]
455    fn test_single_message_perror()
456    {
457        /*use std::sync::Arc;
458        use std::thread;
459        use std::time::Duration;
460        use super::{LOG_MASK};*/
461
462        let log = 
463            SyncSyslog::openlog(
464                    Some("test2"), 
465                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID | LogStat::LOG_PERROR, 
466                    LogFacility::LOG_DAEMON,
467                    SyslogLocal::new()
468                );
469
470        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
471
472        let log = log.unwrap();
473
474        log.syslog(Priority::LOG_DEBUG, format!("perror test UTF-8 きるさお命泉ぶねりよ日子金れっ проверка BOM").into());
475
476        let _ = log.closelog();
477
478        return;
479    }
480
481    #[test]
482    fn test_multithreading()
483    {
484        use std::sync::Arc;
485        use std::thread;
486        use std::time::{Instant, Duration};
487
488        let log = 
489                SyncSyslog::openlog(
490                    Some("test_multithreading"), 
491                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
492                    LogFacility::LOG_DAEMON,
493                SyslogLocal::new()
494            );
495
496        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
497
498        let log = Arc::new(log.unwrap());
499        let c1_log = log.clone();
500        let c2_log = log.clone();
501
502        thread::spawn(move|| {
503            for i in 0..5
504            {
505                //thread::sleep(Duration::from_nanos(200));
506                let fmmt = format!("a message from thread 1 #{}[]", i);
507                let now = Instant::now();
508                c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
509                let elapsed = now.elapsed();
510                println!("t1: {:?}", elapsed);
511            }
512        });
513
514        thread::spawn(move|| {
515            for i in 0..5
516            {
517                //thread::sleep(Duration::from_nanos(201));
518                let fmmt = format!("きるさお命泉ぶねりよ日子金れっ {}", i);
519                let now = Instant::now();
520                c2_log.syslog(Priority::LOG_DEBUG, fmmt.into());
521                let elapsed = now.elapsed();
522                println!("t2: {:?}", elapsed);
523            }
524        });
525
526        let now = Instant::now();
527        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
528        let elapsed = now.elapsed();
529        println!("main: {:?}", elapsed);
530
531        thread::sleep(Duration::from_secs(2));
532
533        let _ = log.closelog();
534
535        return;
536    }
537
538    #[test]
539    fn test_multithreading_rw()
540    {
541        use std::sync::Arc;
542        use std::thread;
543        use std::time::{Instant, Duration};
544
545        let log: Result<SyncSyslog, crate::error::SyslogError> = 
546                SyncSyslog::openlog(
547                    Some("test_multithreading_rw"), 
548                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
549                    LogFacility::LOG_DAEMON,
550                SyslogLocal::new()
551            );
552
553        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
554
555        let log = Arc::new(log.unwrap());
556        let c1_log = log.clone();
557
558        let thread_handler = 
559            thread::spawn(move|| 
560                {
561                    std::thread::park();
562                    for i in 0..30
563                    {
564                        
565
566                        let fmmt = format!("a message from thread 1 #{}[]", i);
567                        let now = Instant::now();
568                        c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
569                        let elapsed = now.elapsed();
570                        println!("t1: {:?}", elapsed);
571                    }
572                }
573            );
574
575        let now = Instant::now();
576        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
577        let elapsed = now.elapsed();
578        println!("main: {:?}", elapsed);
579
580        thread_handler.thread().unpark();
581
582        for i in 0..3
583        {
584            std::thread::sleep(Duration::from_nanos(999));
585            let identity = format!("multithreading_rw{}", i);
586            let now = Instant::now();
587            log.change_identity(Some(&identity)).unwrap();
588            let elapsed = now.elapsed();
589            println!("idc: {:?}", elapsed);
590        }
591
592        thread_handler.join().unwrap();
593
594        let _ = log.closelog();
595
596        return;
597    }
598
599    #[test]
600    fn test_multithreading_rw_sock()
601    {
602        use std::sync::Arc;
603        use std::thread;
604        use std::time::{Instant, Duration};
605
606        let log = 
607                SyncSyslog::openlog(
608                    Some("multithreading_rw_sock"), 
609                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
610                    LogFacility::LOG_DAEMON,
611                SyslogLocal::new()
612            );
613
614        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
615
616        let log = Arc::new(log.unwrap());
617        let c1_log = log.clone();
618
619        let thread_handler = 
620            thread::spawn(move|| 
621                {
622                    std::thread::park();
623                    for i in 0..30
624                    {
625                        
626
627                        let fmmt = format!("a message from thread 1 #{}[]", i);
628                        let now = Instant::now();
629                        c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
630                        let elapsed = now.elapsed();
631                        println!("t1: {:?}", elapsed);
632                    }
633                }
634            );
635
636        let now = Instant::now();
637        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
638        let elapsed = now.elapsed();
639        println!("main: {:?}", elapsed);
640
641        thread_handler.thread().unpark();
642
643        for _ in 0..3
644        {
645            std::thread::sleep(Duration::from_nanos(999));
646            let now = Instant::now();
647            log.update_tap_data(SyslogLocal::new()).unwrap();
648            let elapsed = now.elapsed();
649            println!("idc: {:?}", elapsed);
650        }
651
652        thread_handler.join().unwrap();
653
654        let _ = log.closelog();
655
656        return;
657    }
658
659    #[test]
660    fn long_msg_test()
661    {
662        // 40 EMSGSIZE
663        let msg = 
664    "7赤ざクぽな載覧な改申ほふ取容う主坊酸ヱ司戦ヒソオ力端めゃ間真ル実記キ団需くスルて学回県仁京ぴ熱完かあもく。上ょぜ催5強変却ソヲキ転入ク記事購シリ断衝ぽ玲面たぽつへ様態の善無かー勢加ヨマナキ趣会撮さはこ違42器のレうゆ。稿エスタ己報照アイネル岩撲ムニ半者サアキツ画47込死請誌8策ノ再然ださそ禁断しにた高否リ続最ユケ山芸ロ去群づへ索芭あン掲佳怖斎澤クね。
665    書キマコヒ上広ざばてわ会佐のにりリ学総点フわすか頼野ぜイよば株約ネキヱメ必軽チヲ録使ラ下能ナウコ紀捜れ霊別イ摯療じらどト相3聞めびら情拳ユフエ確経板植えーぜあ。無ど曲注程クタル系新どばくい都面村リと計安ワヱ月見モヌエノ完臨健85定テサコミ貸容ミテタカ写載とかえげ詐訃だみそな。代け設養テヨナ乱54服料ニ止画ら不暮ッ強治ぱンやし供方広づじもあ般判ごくドラ示刊ヱサトキ速事取さふぞ授共西れッ。
666    陸オク康59面くこ惑7伊エノモ候余ロソウ政投ナク転文だけス香両4誕よ数真ひぞぴざ空加ユラ勢隣ゃびよ移72士シヌ図際想カマテ覧費活輸権因ん。東がイ価変や濃恒ヒメネエ学見ょ理供カオムヱ針中わば文63転ヨリホミ礼民ネトマツ速果還ばが転世晴げでんが。犯レト同岸サケ写新ゆぐぱひ人捕けほゅえ的人第いぜ転連ぎど京分株ニムトヒ家及ユフケヌ記定み歩死質をゃいイ都末ワ革量んつ覧打百レいん。
667    下ゃとぞら川株以東ぴそぱ費更ウマヨメ覧論ウスレモ八度ずんとイ発平う果構つ小各ぼス夢国フラ連石はちい雪飲聴ゅいと。門ぱし続消上ト文影投設テユチ設川ルラシケ引押ヤマセメ権書ハテ例発リロソイ環載ぴ企実カマリト店鉄ワソロフ逆子先チルマ楽法どゆね声東女携抜爆んけみ。14報ふラめて怒止に開謙こさ促大ヘチツ遺飯ケ営長コキ価空少ろッひぱ読信ケテウ者育ヒミク代57柱浪フ。
668    ";
669
670    println!("{}", msg.len());
671
672        let log = 
673                SyncSyslog::openlog(
674                    Some("test4"), 
675                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
676                    LogFacility::LOG_DAEMON,
677                    SyslogLocal::new()
678                );
679
680        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
681
682        let log = log.unwrap();
683
684        log.syslog(Priority::LOG_DEBUG, format!("{}", msg).into());
685                    
686        let _ = log.closelog();
687
688        return;
689    }
690}
691
692#[cfg(target_family = "windows")]
693#[cfg(test)]
694mod tests
695{
696    use crate::
697    {
698        LogFacility, LogStat, Priority, SyStreamApi, SyncSyslog, SyslogApi, WindowsEvent 
699    };
700
701    #[test]
702    fn test_single_message()
703    {
704
705        let log = 
706            SyncSyslog::openlog(
707                Some("test1"), 
708                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
709                LogFacility::LOG_DAEMON,
710            WindowsEvent::new()
711        );
712
713        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
714
715        let log = log.unwrap();
716
717        let msg1 = format!("test UTF-8 проверка BOM UTF-8");
718        let now = std::time::Instant::now();
719
720        log.syslog(Priority::LOG_DEBUG, msg1.into());
721
722        let dur = now.elapsed();
723        println!("{:?}", dur);
724
725        let msg2 = format!("test UTF-8 2 きるさお命泉ぶねりよ日子金れっ");
726
727        let now = std::time::Instant::now();
728
729        log.syslog(Priority::LOG_DEBUG, msg2.into());
730
731        let dur = now.elapsed();
732        println!("{:?}", dur);
733
734        let _ = log.closelog();
735
736        return;
737    }
738
739   /* mod testsss
740    {
741        use std::{ffi::CString, mem::transmute, ptr::null};
742
743        use windows::{Win32::System::EventLog::{EVENTLOG_SUCCESS, OpenEventLogA, REPORT_EVENT_TYPE, RegisterEventSourceA, ReportEventA}, core::{PCSTR, Param}};
744
745    #[test]
746    fn test222()
747    {
748        let sss = CString::new("testSource123").unwrap();
749        let sss2: *const u8 = unsafe { transmute(sss.as_ptr()) };
750        let evs = 
751            unsafe {  /*OpenEventLogA*/RegisterEventSourceA(PCSTR::null(), PCSTR::from_raw(sss2) )}
752                .unwrap();
753
754        let testmsd = CString::new("message 123").unwrap();
755        let msgs = &[PCSTR::from_raw( unsafe { transmute(testmsd.as_ptr()) })];
756        unsafe 
757        {
758            ReportEventA(evs, EVENTLOG_SUCCESS, 1, 0x80000000, 
759                None, 0, Some(msgs), None)
760            };
761    }
762}*/
763
764    #[test]
765    fn test_single_stream_test()
766    {
767        use std::fmt::Write;
768
769        let log = 
770            SyncSyslog::openlog(
771                Some("test1"), 
772                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
773                LogFacility::LOG_DAEMON,
774            WindowsEvent::new());
775
776        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
777
778        let log = log.unwrap();
779        
780        write!(log.stream(Priority::LOG_DEBUG), "test123").unwrap();
781
782    }
783
784    #[test]
785    fn test_single_message_withound_nd()
786    {
787
788        let log = 
789            SyncSyslog::openlog(
790                Some("test1_nond"), 
791                LogStat::LOG_CONS | LogStat::LOG_PID, 
792                LogFacility::LOG_DAEMON,
793            WindowsEvent::new());
794
795        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
796
797        let log = log.unwrap();
798
799        let msg1 = format!("test UTF-8 проверка BOM UTF-8");
800        let now = std::time::Instant::now();
801
802        log.syslog(Priority::LOG_DEBUG, msg1.into());
803
804        let dur = now.elapsed();
805        println!("{:?}", dur);
806
807        let msg2 = format!("test UTF-8  きるさお命泉ぶねりよ日子金れっ");
808
809        let now = std::time::Instant::now();
810
811        log.syslog(Priority::LOG_DEBUG, msg2.into());
812
813        let dur = now.elapsed();
814        println!("{:?}", dur);
815
816        let _ = log.closelog();
817
818        return;
819    }
820
821    #[test]
822    fn test_single_message_perror()
823    {
824        /*use std::sync::Arc;
825        use std::thread;
826        use std::time::Duration;
827        use super::{LOG_MASK};*/
828
829        let log = 
830            SyncSyslog::openlog(
831                    Some("test2"), 
832                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID | LogStat::LOG_PERROR, 
833                    LogFacility::LOG_DAEMON,
834                    WindowsEvent::new()
835                );
836
837        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
838
839        let log = log.unwrap();
840
841        log.syslog(Priority::LOG_DEBUG, format!("perror test UTF-8 きるさお命泉ぶねりよ日子金れっ проверка BOM").into());
842
843        let _ = log.closelog();
844
845        return;
846    }
847
848    #[test]
849    fn test_multithreading()
850    {
851        use std::sync::Arc;
852        use std::thread;
853        use std::time::{Instant, Duration};
854
855        let log = 
856                SyncSyslog::openlog(
857                    Some("test_multithreading"), 
858                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
859                    LogFacility::LOG_DAEMON,
860                WindowsEvent::new()
861            );
862
863        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
864
865        let log = Arc::new(log.unwrap());
866        let c1_log = log.clone();
867        let c2_log = log.clone();
868
869        thread::spawn(move|| {
870            for i in 0..5
871            {
872                //thread::sleep(Duration::from_nanos(200));
873                let fmmt = format!("a message from thread 1 #{}[]", i);
874                let now = Instant::now();
875                c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
876                let elapsed = now.elapsed();
877                println!("t1: {:?}", elapsed);
878            }
879        });
880
881        thread::spawn(move|| {
882            for i in 0..5
883            {
884                //thread::sleep(Duration::from_nanos(201));
885                let fmmt = format!("きるさお命泉ぶねりよ日子金れっ {}", i);
886                let now = Instant::now();
887                c2_log.syslog(Priority::LOG_DEBUG, fmmt.into());
888                let elapsed = now.elapsed();
889                println!("t2: {:?}", elapsed);
890            }
891        });
892
893        let now = Instant::now();
894        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
895        let elapsed = now.elapsed();
896        println!("main: {:?}", elapsed);
897
898        thread::sleep(Duration::from_secs(2));
899
900        let _ = log.closelog();
901
902        return;
903    }
904
905    #[test]
906    fn test_multithreading_rw()
907    {
908        use std::sync::Arc;
909        use std::thread;
910        use std::time::{Instant, Duration};
911
912        let log: Result<SyncSyslog, crate::error::SyslogError> = 
913                SyncSyslog::openlog(
914                    Some("test_multithreading_rw"), 
915                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
916                    LogFacility::LOG_DAEMON,
917                WindowsEvent::new()
918            );
919
920        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
921
922        let log = Arc::new(log.unwrap());
923        let c1_log = log.clone();
924
925        let thread_handler = 
926            thread::spawn(move|| 
927                {
928                    std::thread::park();
929                    for i in 0..30
930                    {
931                        
932
933                        let fmmt = format!("a message from thread 1 #{}[]", i);
934                        let now = Instant::now();
935                        c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
936                        let elapsed = now.elapsed();
937                        println!("t1: {:?}", elapsed);
938                    }
939                }
940            );
941
942        let now = Instant::now();
943        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
944        let elapsed = now.elapsed();
945        println!("main: {:?}", elapsed);
946
947        thread_handler.thread().unpark();
948
949        for i in 0..3
950        {
951            std::thread::sleep(Duration::from_nanos(999));
952            let identity = format!("multithreading_rw{}", i);
953            let now = Instant::now();
954            log.change_identity(Some(&identity)).unwrap();
955            let elapsed = now.elapsed();
956            println!("idc: {:?}", elapsed);
957        }
958
959        thread_handler.join().unwrap();
960
961        let _ = log.closelog();
962
963        return;
964    }
965
966    #[test]
967    fn test_multithreading_rw_sock()
968    {
969        use std::sync::Arc;
970        use std::thread;
971        use std::time::{Instant, Duration};
972
973        let log = 
974                SyncSyslog::openlog(
975                    Some("multithreading_rw_sock"), 
976                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
977                    LogFacility::LOG_DAEMON,
978                WindowsEvent::new()
979            );
980
981        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
982
983        let log = Arc::new(log.unwrap());
984        let c1_log = log.clone();
985
986        let thread_handler = 
987            thread::spawn(move|| 
988                {
989                    std::thread::park();
990                    for i in 0..30
991                    {
992                        
993
994                        let fmmt = format!("a message from thread 1 #{}[]", i);
995                        let now = Instant::now();
996                        c1_log.syslog(Priority::LOG_DEBUG, fmmt.into());
997                        let elapsed = now.elapsed();
998                        println!("t1: {:?}", elapsed);
999                    }
1000                }
1001            );
1002
1003        let now = Instant::now();
1004        log.syslog(Priority::LOG_DEBUG, format!("A message from main, きるさお命泉ぶねりよ日子金れっ").into());
1005        let elapsed = now.elapsed();
1006        println!("main: {:?}", elapsed);
1007
1008        thread_handler.thread().unpark();
1009
1010        for _ in 0..3
1011        {
1012            std::thread::sleep(Duration::from_nanos(999));
1013            let now = Instant::now();
1014            log.update_tap_data(WindowsEvent::new()).unwrap();
1015            let elapsed = now.elapsed();
1016            println!("idc: {:?}", elapsed);
1017        }
1018
1019        thread_handler.join().unwrap();
1020
1021        let _ = log.closelog();
1022
1023        return;
1024    }
1025
1026    #[test]
1027    fn long_msg_test()
1028    {
1029        // 40 EMSGSIZE
1030        let msg = 
1031    "7赤ざクぽな載覧な改申ほふ取容う主坊酸ヱ司戦ヒソオ力端めゃ間真ル実記キ団需くスルて学回県仁京ぴ熱完かあもく。上ょぜ催5強変却ソヲキ転入ク記事購シリ断衝ぽ玲面たぽつへ様態の善無かー勢加ヨマナキ趣会撮さはこ違42器のレうゆ。稿エスタ己報照アイネル岩撲ムニ半者サアキツ画47込死請誌8策ノ再然ださそ禁断しにた高否リ続最ユケ山芸ロ去群づへ索芭あン掲佳怖斎澤クね。
1032    書キマコヒ上広ざばてわ会佐のにりリ学総点フわすか頼野ぜイよば株約ネキヱメ必軽チヲ録使ラ下能ナウコ紀捜れ霊別イ摯療じらどト相3聞めびら情拳ユフエ確経板植えーぜあ。無ど曲注程クタル系新どばくい都面村リと計安ワヱ月見モヌエノ完臨健85定テサコミ貸容ミテタカ写載とかえげ詐訃だみそな。代け設養テヨナ乱54服料ニ止画ら不暮ッ強治ぱンやし供方広づじもあ般判ごくドラ示刊ヱサトキ速事取さふぞ授共西れッ。
1033    陸オク康59面くこ惑7伊エノモ候余ロソウ政投ナク転文だけス香両4誕よ数真ひぞぴざ空加ユラ勢隣ゃびよ移72士シヌ図際想カマテ覧費活輸権因ん。東がイ価変や濃恒ヒメネエ学見ょ理供カオムヱ針中わば文63転ヨリホミ礼民ネトマツ速果還ばが転世晴げでんが。犯レト同岸サケ写新ゆぐぱひ人捕けほゅえ的人第いぜ転連ぎど京分株ニムトヒ家及ユフケヌ記定み歩死質をゃいイ都末ワ革量んつ覧打百レいん。
1034    下ゃとぞら川株以東ぴそぱ費更ウマヨメ覧論ウスレモ八度ずんとイ発平う果構つ小各ぼス夢国フラ連石はちい雪飲聴ゅいと。門ぱし続消上ト文影投設テユチ設川ルラシケ引押ヤマセメ権書ハテ例発リロソイ環載ぴ企実カマリト店鉄ワソロフ逆子先チルマ楽法どゆね声東女携抜爆んけみ。14報ふラめて怒止に開謙こさ促大ヘチツ遺飯ケ営長コキ価空少ろッひぱ読信ケテウ者育ヒミク代57柱浪フ。
1035    ";
1036
1037    println!("{}", msg.len());
1038
1039        let log = 
1040                SyncSyslog::openlog(
1041                    Some("test4"), 
1042                    LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
1043                    LogFacility::LOG_DAEMON,
1044                    WindowsEvent::new()
1045                );
1046
1047        assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
1048
1049        let log = log.unwrap();
1050
1051        log.syslog(Priority::LOG_DEBUG, format!("{}", msg).into());
1052                    
1053        let _ = log.closelog();
1054
1055        return;
1056    }
1057}